You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
4.5 KiB
146 lines
4.5 KiB
#!/usr/bin/env bash |
|
set -euo pipefail |
|
|
|
# Run the relay with CPU profiling enabled, wait 60s, then open the |
|
# generated profile using `go tool pprof` web UI. |
|
# |
|
# Notes: |
|
# - Builds a temporary relay binary in /tmp and deletes it on exit. |
|
# - Uses the exact env requested, plus ORLY_PPROF=cpu and a deterministic |
|
# ORLY_PPROF_PATH inside a temp dir. |
|
# - Profiles for DURATION seconds (default 60). |
|
# - Launches pprof web UI at http://localhost:8000 and attempts to open browser. |
|
|
|
DURATION="${DURATION:-60}" |
|
HEALTH_PORT="${HEALTH_PORT:-18081}" |
|
ROOT_DIR="/home/mleku/src/next.orly.dev" |
|
LISTEN_HOST="${LISTEN_HOST:-10.0.0.2}" |
|
|
|
cd "$ROOT_DIR" |
|
|
|
# Refresh embedded web assets |
|
reset || true |
|
./scripts/update-embedded-web.sh || true |
|
|
|
TMP_DIR="$(mktemp -d -t orly-pprof-XXXXXX)" |
|
BIN_PATH="$TMP_DIR/next.orly.dev" |
|
LOG_FILE="$TMP_DIR/relay.log" |
|
PPROF_FILE="" |
|
RELAY_PID="" |
|
PPROF_DIR="$TMP_DIR/profiles" |
|
mkdir -p "$PPROF_DIR" |
|
|
|
cleanup() { |
|
# Try to stop relay if still running |
|
if [[ -n "${RELAY_PID}" ]] && kill -0 "${RELAY_PID}" 2>/dev/null; then |
|
kill "${RELAY_PID}" || true |
|
wait "${RELAY_PID}" || true |
|
fi |
|
rm -f "$BIN_PATH" 2>/dev/null || true |
|
rm -rf "$TMP_DIR" 2>/dev/null || true |
|
} |
|
trap cleanup EXIT |
|
|
|
echo "[run-relay-pprof] Building relay binary ..." |
|
GOFLAGS="${GOFLAGS:-}" go build -o "$BIN_PATH" . |
|
|
|
echo "[run-relay-pprof] Starting relay with CPU profiling ..." |
|
( |
|
ORLY_LOG_LEVEL=debug \ |
|
ORLY_LISTEN="$LISTEN_HOST" \ |
|
ORLY_PORT=3334 \ |
|
ORLY_ADMINS=npub1fjqqy4a93z5zsjwsfxqhc2764kvykfdyttvldkkkdera8dr78vhsmmleku \ |
|
ORLY_ACL_MODE=follows \ |
|
ORLY_RELAY_ADDRESSES=test.orly.dev \ |
|
ORLY_IP_BLACKLIST=192.71.213.188 \ |
|
ORLY_HEALTH_PORT="$HEALTH_PORT" \ |
|
ORLY_ENABLE_SHUTDOWN=true \ |
|
ORLY_PPROF_HTTP=true \ |
|
ORLY_OPEN_PPROF_WEB=true \ |
|
"$BIN_PATH" |
|
) >"$LOG_FILE" 2>&1 & |
|
RELAY_PID=$! |
|
|
|
# Wait for pprof HTTP server readiness |
|
PPROF_BASE="http://${LISTEN_HOST}:6060" |
|
echo "[run-relay-pprof] Waiting for pprof at ${PPROF_BASE} ..." |
|
for i in {1..100}; do |
|
if curl -fsS "${PPROF_BASE}/debug/pprof/" -o /dev/null 2>/dev/null; then |
|
READY=1 |
|
break |
|
fi |
|
sleep 0.2 |
|
done |
|
if [[ -z "${READY:-}" ]]; then |
|
echo "[run-relay-pprof] ERROR: pprof HTTP server not reachable at ${PPROF_BASE}." >&2 |
|
echo "[run-relay-pprof] Check that ${LISTEN_HOST} is a local bindable address." >&2 |
|
# Attempt to dump recent logs for context |
|
tail -n 100 "$LOG_FILE" || true |
|
# Try INT to clean up |
|
killall -INT next.orly.dev 2>/dev/null || true |
|
exit 1 |
|
fi |
|
|
|
# Open the HTTP pprof UI |
|
( xdg-open "${PPROF_BASE}/debug/pprof/" >/dev/null 2>&1 || true ) & |
|
|
|
echo "[run-relay-pprof] Collecting CPU profile via HTTP for ${DURATION}s ..." |
|
# The HTTP /debug/pprof/profile endpoint records CPU for the provided seconds |
|
# and returns a pprof file without needing to stop the process. |
|
curl -fsS --max-time $((DURATION+10)) \ |
|
"${PPROF_BASE}/debug/pprof/profile?seconds=${DURATION}" \ |
|
-o "$PPROF_DIR/cpu.pprof" || true |
|
|
|
echo "[run-relay-pprof] Sending SIGINT (Ctrl+C) for graceful shutdown ..." |
|
killall -INT next.orly.dev 2>/dev/null || true |
|
|
|
# Wait up to ~60s for graceful shutdown so defers (pprof Stop) can run |
|
for i in {1..300}; do |
|
if ! pgrep -x next.orly.dev >/dev/null 2>&1; then |
|
break |
|
fi |
|
sleep 0.2 |
|
done |
|
|
|
# Try HTTP shutdown if still running (ensures defer paths can run) |
|
if pgrep -x next.orly.dev >/dev/null 2>&1; then |
|
echo "[run-relay-pprof] Still running, requesting /shutdown ..." |
|
curl -fsS --max-time 2 "http://10.0.0.2:${HEALTH_PORT}/shutdown" >/dev/null 2>&1 || true |
|
for i in {1..150}; do |
|
if ! pgrep -x next.orly.dev >/dev/null 2>&1; then |
|
break |
|
fi |
|
sleep 0.2 |
|
done |
|
fi |
|
if pgrep -x next.orly.dev >/dev/null 2>&1; then |
|
echo "[run-relay-pprof] Escalating: sending SIGTERM ..." |
|
killall -TERM next.orly.dev 2>/dev/null || true |
|
for i in {1..150}; do |
|
if ! pgrep -x next.orly.dev >/dev/null 2>&1; then |
|
break |
|
fi |
|
sleep 0.2 |
|
done |
|
fi |
|
if pgrep -x next.orly.dev >/dev/null 2>&1; then |
|
echo "[run-relay-pprof] Force kill: sending SIGKILL ..." |
|
killall -KILL next.orly.dev 2>/dev/null || true |
|
fi |
|
|
|
PPROF_FILE="$PPROF_DIR/cpu.pprof" |
|
if [[ ! -s "$PPROF_FILE" ]]; then |
|
echo "[run-relay-pprof] ERROR: HTTP CPU profile not captured (file empty)." >&2 |
|
echo "[run-relay-pprof] Hint: Ensure ORLY_PPROF_HTTP=true and port 6060 is reachable." >&2 |
|
exit 1 |
|
fi |
|
|
|
echo "[run-relay-pprof] Detected profile file: $PPROF_FILE" |
|
echo "[run-relay-pprof] Launching 'go tool pprof' web UI on :8000 ..." |
|
|
|
# Try to open a browser automatically, ignore failures |
|
( sleep 0.6; xdg-open "http://localhost:8000" >/dev/null 2>&1 || true ) & |
|
|
|
exec go tool pprof -http=:8000 "$BIN_PATH" "$PPROF_FILE" |
|
|
|
|
|
|