#!/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