feat: add privacy-safe server diagnostics
This commit is contained in:
1 parent
2360506607
commit
a3963ad0f6
27 files changed
+1305
-112
No files matched your search
Executable
+97
@@ -0,0 +1,97 @@
|
||||
#!/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
|
||||
@@ -13,5 +13,5 @@ fi
|
||||
|
||||
npm test
|
||||
npm run build
|
||||
sh -n infra/backup-postgres.sh infra/restore-check.sh
|
||||
sh -n infra/backup-postgres.sh infra/restore-check.sh infra/diagnose-server.sh
|
||||
printf '%s\n' 'predeploy-check: static, test, build, and script gates passed'
|
||||
Reference in new issue
Block a user