Files
agentic-codemod-pipeline/llm/scripts/logs.sh
T
2026-08-29 13:17:59 +02:00

109 lines
3.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# Podgląd logów backendu LLM - jedno wejście niezależnie od tego, czy backend
# działa w kontenerze (vllm-gpu) czy jako proces z plikiem logu (vllm-metal, ollama, mock).
#
# Użycie:
# logs.sh --backend vllm-gpu [--tail 100] [--follow|--no-follow] [--grep WZORZEC] [--save PLIK]
#
# Domyślnie śledzi na bieżąco (jak `tail -f`). --no-follow robi jednorazowy zrzut,
# co jest tym, czego się chce przy wklejaniu fragmentu do zgłoszenia.
set -euo pipefail
# Ctrl-C przy śledzeniu logów to normalne zakończenie, nie awaria - bez tego
# go-task raportowałby "Failed to run task" za każdym razem, gdy ktoś przerwie podgląd.
trap 'exit 0' INT TERM
BACKEND=""
RUN_DIR=".runs/llm"
TAIL="100"
FOLLOW="true"
PATTERN=""
SAVE=""
COMPOSE_FILE="llm/docker-compose.yml"
usage() { sed -n '2,12p' "$0" >&2; exit "${1:-1}"; }
while [ $# -gt 0 ]; do
case "$1" in
--backend) BACKEND="${2:?}"; shift 2 ;;
--run-dir) RUN_DIR="${2:?}"; shift 2 ;;
--tail) TAIL="${2:?}"; shift 2 ;;
--grep) PATTERN="${2:?}"; shift 2 ;;
--save) SAVE="${2:?}"; shift 2 ;;
--follow) FOLLOW="true"; shift ;;
--no-follow) FOLLOW="false"; shift ;;
-h|--help) usage 0 ;;
*) echo "nieznany argument: $1" >&2; usage ;;
esac
done
[ -n "$BACKEND" ] || { echo "podaj --backend" >&2; exit 1; }
# Zapis do pliku bez sensu w trybie śledzenia - zrzut ma się skończyć.
[ -n "$SAVE" ] && FOLLOW="false"
log_file_for() {
case "$1" in
vllm-metal) echo "$RUN_DIR/vllm-metal.log" ;;
ollama) echo "$RUN_DIR/ollama.log" ;;
mock) echo "$RUN_DIR/mock.log" ;;
*) echo "" ;;
esac
}
# Strumień logów na stdout, zależnie od backendu.
emit() {
if [ "$BACKEND" = "vllm-gpu" ]; then
command -v docker >/dev/null 2>&1 || { echo "brak dockera - a backend vllm-gpu działa w kontenerze" >&2; exit 1; }
if [ "$FOLLOW" = "true" ]; then
docker compose -f "$COMPOSE_FILE" --profile vllm-gpu logs --follow --tail "$TAIL"
else
docker compose -f "$COMPOSE_FILE" --profile vllm-gpu logs --tail "$TAIL"
fi
return
fi
local file
file="$(log_file_for "$BACKEND")"
if [ -z "$file" ]; then
echo "backend '$BACKEND' nie ma znanego źródła logów" >&2
exit 1
fi
if [ ! -f "$file" ]; then
echo "brak pliku logu: $file" >&2
echo "backend prawdopodobnie nie był uruchamiany - zacznij od: task llm:up" >&2
exit 1
fi
if [ "$FOLLOW" = "true" ]; then
# --follow=name odtwarza plik po rotacji/nadpisaniu, np. przy restarcie backendu
tail -n "$TAIL" -F "$file"
else
tail -n "$TAIL" "$file"
fi
}
filter() {
if [ -n "$PATTERN" ]; then
# --line-buffered: przy śledzeniu linie mają się pojawiać od razu, a nie po zapełnieniu bufora
grep --line-buffered -Ei "$PATTERN" || true
else
cat
fi
}
if [ -n "$SAVE" ]; then
mkdir -p "$(dirname "$SAVE")"
emit | filter > "$SAVE"
echo "zapisano $(wc -l < "$SAVE" | tr -d ' ') linii do $SAVE"
elif [ "$FOLLOW" = "true" ]; then
emit | filter
else
# Jednorazowy zrzut: pusty wynik przy filtrze jest dwuznaczny (brak dopasowań
# czy brak logów?), więc mówimy to wprost zamiast milczeć.
output="$(emit | filter)"
if [ -z "$output" ] && [ -n "$PATTERN" ]; then
echo "brak linii pasujących do '$PATTERN' w ostatnich $TAIL liniach logu" >&2
else
printf '%s\n' "$output"
fi
fi