98 lines
2.7 KiB
Bash
Executable File
98 lines
2.7 KiB
Bash
Executable File
#!/usr/bin/env sh
|
|
set -eu
|
|
|
|
since=30m
|
|
tail_lines=1000
|
|
match=
|
|
all_services=false
|
|
|
|
usage() {
|
|
printf '%s\n' 'Usage: sh infra/diagnose-server.sh [--since 30m] [--tail 1000] [--match VALUE] [--all-services]'
|
|
printf '%s\n' 'Filters are literal and can be a request ID, TASK-* ID, AgentBus frame/conversation/channel ID, diagnostic event, or error code.'
|
|
}
|
|
|
|
while [ "$#" -gt 0 ]; do
|
|
case "$1" in
|
|
--since)
|
|
[ "$#" -ge 2 ] || { usage >&2; exit 2; }
|
|
since=$2
|
|
shift 2
|
|
;;
|
|
--tail)
|
|
[ "$#" -ge 2 ] || { usage >&2; exit 2; }
|
|
tail_lines=$2
|
|
shift 2
|
|
;;
|
|
--match)
|
|
[ "$#" -ge 2 ] || { usage >&2; exit 2; }
|
|
match=$2
|
|
shift 2
|
|
;;
|
|
--all-services)
|
|
all_services=true
|
|
shift
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
usage >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if ! printf '%s' "$since" | grep -Eq '^[0-9]+[smhd]$'; then
|
|
printf '%s\n' 'diagnose-server: --since must use a bounded value such as 30m, 2h, or 1d.' >&2
|
|
exit 2
|
|
fi
|
|
case "$tail_lines" in
|
|
*[!0-9]*|'')
|
|
printf '%s\n' 'diagnose-server: --tail must be a positive integer.' >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
if [ "$tail_lines" -lt 1 ] || [ "$tail_lines" -gt 50000 ]; then
|
|
printf '%s\n' 'diagnose-server: --tail must be between 1 and 50000.' >&2
|
|
exit 2
|
|
fi
|
|
|
|
cd "$(dirname "$0")/.."
|
|
|
|
compose() {
|
|
if [ -f .env.production ]; then
|
|
docker compose --env-file .env.production "$@"
|
|
else
|
|
docker compose "$@"
|
|
fi
|
|
}
|
|
|
|
command -v docker >/dev/null 2>&1 || {
|
|
printf '%s\n' 'diagnose-server: docker is not installed or not on PATH.' >&2
|
|
exit 1
|
|
}
|
|
|
|
printf '%s\n' 'Container state:'
|
|
compose ps
|
|
|
|
printf '%s\n' 'Control-plane readiness:'
|
|
if ! compose exec -T control-plane node -e "fetch('http://127.0.0.1:8786/health/ready').then(async response => { const body = await response.json(); console.log(JSON.stringify({ status: response.status, body })); process.exit(response.ok ? 0 : 1); }).catch(error => { console.error(JSON.stringify({ status: 0, error_code: error && error.code ? String(error.code) : 'health_request_failed' })); process.exit(1); });"; then
|
|
printf '%s\n' 'diagnose-server: readiness is unhealthy; recent logs follow.' >&2
|
|
fi
|
|
|
|
printf 'Recent logs (since=%s, tail=%s):\n' "$since" "$tail_lines"
|
|
if [ "$all_services" = true ]; then
|
|
if [ -n "$match" ]; then
|
|
compose logs --no-color --timestamps --since "$since" --tail "$tail_lines" \
|
|
| grep -F -- "$match" || true
|
|
else
|
|
compose logs --no-color --timestamps --since "$since" --tail "$tail_lines"
|
|
fi
|
|
elif [ -n "$match" ]; then
|
|
compose logs --no-color --timestamps --since "$since" --tail "$tail_lines" control-plane \
|
|
| grep -F -- "$match" || true
|
|
else
|
|
compose logs --no-color --timestamps --since "$since" --tail "$tail_lines" control-plane
|
|
fi
|