115 lines
4.1 KiB
Bash
Executable File
115 lines
4.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# kandev-logs — fetch logs for a running kandev instance by backend port.
|
|
#
|
|
# Two modes:
|
|
# --export (default) GET /api/v1/system/debug/export[?level=LEVEL], pretty
|
|
# printed with jq. This is the structured in-memory log
|
|
# buffer + runtime metadata.
|
|
# --tail Tail the stderr log file written by dev-isolated
|
|
# (/tmp/kandev-iso-<port>-*/backend.log), or a file given
|
|
# with --file.
|
|
#
|
|
# Usage:
|
|
# scripts/kandev-logs <backend_port> [--export] [--level LEVEL]
|
|
# scripts/kandev-logs <backend_port> --tail [--lines N] [--file PATH]
|
|
#
|
|
# Options:
|
|
# --export Hit the debug-export endpoint (default).
|
|
# --level LEVEL Filter export by level. The export endpoint matches the
|
|
# log entry's level string exactly (zap lowercase levels),
|
|
# so LEVEL must be one of: debug|info|warn|error|dpanic|
|
|
# panic|fatal. Passes ?level=LEVEL and prints only .logs.
|
|
# --tail Tail the backend stderr log file instead of the endpoint.
|
|
# --lines N Lines to show with --tail (default: 80).
|
|
# --file PATH Explicit log file for --tail (overrides auto-resolve).
|
|
# -h, --help Show this help.
|
|
#
|
|
# Examples:
|
|
# scripts/kandev-logs 48429 --export
|
|
# scripts/kandev-logs 48429 --export --level error
|
|
# scripts/kandev-logs 48429 --tail --lines 120
|
|
#
|
|
set -euo pipefail
|
|
|
|
MODE="export"
|
|
LEVEL=""
|
|
LINES=80
|
|
FILE=""
|
|
PORT=""
|
|
|
|
# Levels the export endpoint can match (zapcore.Level.String(), lowercase). The
|
|
# endpoint compares the entry's level string exactly, so any other value would
|
|
# silently match nothing — we reject it up front instead.
|
|
ALLOWED_LEVELS=(debug info warn error dpanic panic fatal)
|
|
|
|
usage() { sed -n '2,31p' "$0" | sed 's/^# \{0,1\}//'; exit "${1:-2}"; }
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--export) MODE="export"; shift ;;
|
|
--tail) MODE="tail"; shift ;;
|
|
--level) LEVEL="${2:?--level requires a value}"; shift 2 ;;
|
|
--lines) LINES="${2:?--lines requires a number}"; shift 2 ;;
|
|
--file) FILE="${2:?--file requires a path}"; shift 2 ;;
|
|
-h|--help) usage 0 ;;
|
|
--*) echo "kandev-logs: unknown flag '$1'" >&2; usage 2 ;;
|
|
*)
|
|
if [[ -z "$PORT" ]]; then PORT="$1"; else
|
|
echo "kandev-logs: unexpected argument '$1'" >&2; usage 2
|
|
fi
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
|
|
[[ -n "$PORT" ]] || { echo "kandev-logs: a backend port is required." >&2; usage 2; }
|
|
[[ "$PORT" =~ ^[0-9]+$ ]] || { echo "kandev-logs: port must be numeric, got '$PORT'" >&2; exit 2; }
|
|
|
|
# Validate --level against the allowed set BEFORE it reaches the URL. An invalid
|
|
# value would otherwise be interpolated into ?level= and silently return zero
|
|
# matching logs, masking the typo.
|
|
if [[ -n "$LEVEL" ]]; then
|
|
level_ok=0
|
|
for lvl in "${ALLOWED_LEVELS[@]}"; do
|
|
[[ "$LEVEL" == "$lvl" ]] && { level_ok=1; break; }
|
|
done
|
|
if [[ "$level_ok" -ne 1 ]]; then
|
|
echo "kandev-logs: invalid --level '$LEVEL'. Allowed: ${ALLOWED_LEVELS[*]}" >&2
|
|
exit 2
|
|
fi
|
|
fi
|
|
|
|
if [[ "$MODE" == "export" ]]; then
|
|
url="http://localhost:$PORT/api/v1/system/debug/export"
|
|
# LEVEL is whitelisted above (alphabetic, no metacharacters), so it is safe to
|
|
# interpolate directly; the query value needs no further encoding.
|
|
[[ -n "$LEVEL" ]] && url="$url?level=$LEVEL"
|
|
if ! body="$(curl -s --fail-with-body "$url" 2>/dev/null)"; then
|
|
echo "kandev-logs: request to $url failed (is the instance on port $PORT up?)" >&2
|
|
exit 1
|
|
fi
|
|
if command -v jq >/dev/null 2>&1; then
|
|
if [[ -n "$LEVEL" ]]; then
|
|
printf '%s' "$body" | jq '.logs'
|
|
else
|
|
printf '%s' "$body" | jq .
|
|
fi
|
|
else
|
|
printf '%s\n' "$body"
|
|
fi
|
|
exit 0
|
|
fi
|
|
|
|
# --- tail mode ---
|
|
if [[ -z "$FILE" ]]; then
|
|
# Resolve the dev-isolated log convention: /tmp/kandev-iso-<port>-*/backend.log
|
|
# Pick the most recent match.
|
|
FILE="$(ls -t /tmp/kandev-iso-"$PORT"-*/backend.log 2>/dev/null | head -1 || true)"
|
|
fi
|
|
[[ -n "$FILE" && -f "$FILE" ]] || {
|
|
echo "kandev-logs: no log file found for port $PORT. Pass --file PATH." >&2
|
|
exit 1
|
|
}
|
|
echo "kandev-logs: tail -n $LINES $FILE" >&2
|
|
tail -n "$LINES" "$FILE"
|