Files
og/scripts/ha-readiness.sh
2026-09-11 06:14:38 +02:00

188 lines
5.2 KiB
Bash

#!/usr/bin/env sh
set -eu
BASE_URL=${BASE_URL:-http://127.0.0.1:8080}
MODEL=${MODEL:-qwen3:8b}
REQUESTS=${REQUESTS:-500}
WARMUP=${WARMUP:-20}
CONCURRENCIES=${CONCURRENCIES:-"1 4 16 32 64"}
OUT_DIR=${OUT_DIR:-"ha-readiness-$(date +%Y%m%d-%H%M%S)"}
TIMEOUT=${TIMEOUT:-2m}
STREAM=${STREAM:-false}
SERVICE_CLASS=${SERVICE_CLASS:-}
CAPTURE_METRICS=${CAPTURE_METRICS:-true}
METRICS_URL=${METRICS_URL:-"${BASE_URL%/}/metrics"}
GATEWAY_PID=${GATEWAY_PID:-}
CAPTURE_RESOURCES=${CAPTURE_RESOURCES:-auto}
CAPTURE_SUSTAINED_RESOURCES=${CAPTURE_SUSTAINED_RESOURCES:-auto}
RESOURCE_SAMPLE_INTERVAL=${RESOURCE_SAMPLE_INTERVAL:-250ms}
RESOURCE_SAMPLE_MAX_DURATION=${RESOURCE_SAMPLE_MAX_DURATION:-15m}
if [ "$CAPTURE_RESOURCES" = "auto" ]; then
if [ -n "$GATEWAY_PID" ]; then
CAPTURE_RESOURCES=true
else
CAPTURE_RESOURCES=false
fi
fi
if [ "$CAPTURE_RESOURCES" = "true" ] && [ -z "$GATEWAY_PID" ]; then
echo "GATEWAY_PID is required when CAPTURE_RESOURCES=true" >&2
exit 2
fi
if [ "$CAPTURE_SUSTAINED_RESOURCES" = "auto" ]; then
if [ -n "$GATEWAY_PID" ]; then
CAPTURE_SUSTAINED_RESOURCES=true
else
CAPTURE_SUSTAINED_RESOURCES=false
fi
fi
if [ "$CAPTURE_SUSTAINED_RESOURCES" = "true" ] && [ -z "$GATEWAY_PID" ]; then
echo "GATEWAY_PID is required when CAPTURE_SUSTAINED_RESOURCES=true" >&2
exit 2
fi
mkdir -p "$OUT_DIR"
SAMPLER_BIN=""
SAMPLER_BG_PID=""
SAMPLER_STOP_FILE=""
cleanup() {
if [ -n "$SAMPLER_STOP_FILE" ]; then
: > "$SAMPLER_STOP_FILE" 2>/dev/null || true
fi
if [ -n "$SAMPLER_BG_PID" ]; then
wait "$SAMPLER_BG_PID" 2>/dev/null || true
fi
if [ -n "$SAMPLER_BIN" ]; then
rm -f "$SAMPLER_BIN"
fi
if [ -n "$SAMPLER_STOP_FILE" ]; then
rm -f "$SAMPLER_STOP_FILE"
fi
}
trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
if [ "$CAPTURE_SUSTAINED_RESOURCES" = "true" ]; then
SAMPLER_BIN="$OUT_DIR/.ha-sampler"
CGO_ENABLED=0 go build -trimpath -o "$SAMPLER_BIN" ./cmd/ha-sampler
fi
echo "HA readiness sweep"
echo "base_url=$BASE_URL model=$MODEL requests=$REQUESTS warmup=$WARMUP stream=$STREAM"
echo "concurrency=$CONCURRENCIES"
echo "capture_metrics=$CAPTURE_METRICS metrics_url=$METRICS_URL"
echo "capture_resources=$CAPTURE_RESOURCES gateway_pid=${GATEWAY_PID:-unset}"
echo "capture_sustained_resources=$CAPTURE_SUSTAINED_RESOURCES sample_interval=$RESOURCE_SAMPLE_INTERVAL"
echo "output=$OUT_DIR"
capture_metrics() {
dst=$1
if [ "$CAPTURE_METRICS" != "true" ]; then
return 0
fi
if ! command -v curl >/dev/null 2>&1; then
echo "curl is required when CAPTURE_METRICS=true" >&2
exit 2
fi
if [ -n "${GATEWAY_BENCH_API_KEY:-}" ]; then
curl -fsS --max-time 30 -H "Authorization: Bearer ${GATEWAY_BENCH_API_KEY}" "$METRICS_URL" > "$dst"
else
curl -fsS --max-time 30 "$METRICS_URL" > "$dst"
fi
}
capture_resources() {
dst=$1
if [ "$CAPTURE_RESOURCES" != "true" ]; then
return 0
fi
go run ./cmd/ha-snapshot -pid "$GATEWAY_PID" -json-out "$dst"
}
start_resource_sampler() {
c=$1
if [ "$CAPTURE_SUSTAINED_RESOURCES" != "true" ]; then
return 0
fi
SAMPLER_STOP_FILE="$OUT_DIR/.resource-sampler-stop-c$c"
rm -f "$SAMPLER_STOP_FILE"
"$SAMPLER_BIN" \
-pid "$GATEWAY_PID" \
-interval "$RESOURCE_SAMPLE_INTERVAL" \
-max-duration "$RESOURCE_SAMPLE_MAX_DURATION" \
-stop-file "$SAMPLER_STOP_FILE" \
-json-out "$OUT_DIR/resources-samples-c$c.json" \
>"$OUT_DIR/resource-sampler-c$c.log" 2>&1 &
SAMPLER_BG_PID=$!
# Give the already-built sampler enough time to capture its initial baseline.
sleep 0.1
if ! kill -0 "$SAMPLER_BG_PID" 2>/dev/null; then
wait "$SAMPLER_BG_PID" || true
echo "resource sampler failed to start for concurrency $c" >&2
cat "$OUT_DIR/resource-sampler-c$c.log" >&2 || true
exit 1
fi
}
stop_resource_sampler() {
c=$1
if [ "$CAPTURE_SUSTAINED_RESOURCES" != "true" ]; then
return 0
fi
: > "$SAMPLER_STOP_FILE"
sampler_rc=0
wait "$SAMPLER_BG_PID" || sampler_rc=$?
rm -f "$SAMPLER_STOP_FILE"
SAMPLER_STOP_FILE=""
SAMPLER_BG_PID=""
if [ "$sampler_rc" -ne 0 ]; then
echo "resource sampler failed for concurrency $c (exit $sampler_rc)" >&2
cat "$OUT_DIR/resource-sampler-c$c.log" >&2 || true
exit "$sampler_rc"
fi
}
for c in $CONCURRENCIES; do
echo "== concurrency $c =="
capture_metrics "$OUT_DIR/metrics-before-c$c.prom"
capture_resources "$OUT_DIR/resources-before-c$c.json"
start_resource_sampler "$c"
set -- go run ./cmd/bench \
-base-url "$BASE_URL" \
-model "$MODEL" \
-concurrency "$c" \
-requests "$REQUESTS" \
-warmup "$WARMUP" \
-timeout "$TIMEOUT" \
-stream="$STREAM" \
-json-out "$OUT_DIR/concurrency-$c.json"
if [ -n "$SERVICE_CLASS" ]; then
set -- "$@" -service-class "$SERVICE_CLASS"
fi
bench_rc=0
"$@" || bench_rc=$?
stop_resource_sampler "$c"
if [ "$bench_rc" -ne 0 ]; then
echo "benchmark failed for concurrency $c (exit $bench_rc)" >&2
exit "$bench_rc"
fi
capture_resources "$OUT_DIR/resources-after-c$c.json"
capture_metrics "$OUT_DIR/metrics-after-c$c.prom"
done
if [ "$CAPTURE_METRICS" = "true" ]; then
go run ./cmd/ha-report \
-input "$OUT_DIR" \
-json-out "$OUT_DIR/report.json" \
-markdown-out "$OUT_DIR/report.md"
else
echo "metrics capture disabled; no reconciled HA evidence report generated"
fi
echo "completed: $OUT_DIR"