#!/usr/bin/env bash set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" . "$ROOT_DIR/scripts/lib.sh" load_env PROFILE="${1:-base}" DURATION="${2:-30}" REPORT_FILE="$ROOT_DIR/dist/bench-$(date +%Y%m%d%H%M%S).json" mkdir -p "$ROOT_DIR/dist" audit "bench" "STARTED" "profile=$PROFILE duration=${DURATION}s" progress "bench" "STARTED" "profile=$PROFILE" require_cmd curl require_cmd docker BASE_URL="${CONSOLE_DOMAIN:-http://localhost}" bench_http() { local name="$1" local url="$2" local concurrency="${3:-10}" local requests="${4:-100}" local pass_rps="${5:-50}" local pass_p99_ms="${6:-500}" printf 'Benchmarking %s (%s)...\n' "$name" "$url" if command -v ab >/dev/null 2>&1; then RAW="$(ab -n "$requests" -c "$concurrency" -q "$url" 2>/dev/null || true)" RPS="$(printf '%s' "$RAW" | grep 'Requests per second' | awk '{print $4}' | cut -d. -f1)" P99="$(printf '%s' "$RAW" | grep '99%' | awk '{print $2}')" RPS="${RPS:-0}" P99="${P99:-9999}" elif command -v wrk >/dev/null 2>&1; then RAW="$(wrk -t2 -c"$concurrency" -d"${DURATION}s" "$url" 2>/dev/null || true)" RPS="$(printf '%s' "$RAW" | grep 'Requests/sec' | awk '{print $2}' | cut -d. -f1)" P99="${P99:-0}" RPS="${RPS:-0}" else # Fallback: sequential curl timing total_ms=0 for _ in $(seq 1 20); do ms="$(curl -sk -o /dev/null -w '%{time_total}' --max-time 5 "$url" 2>/dev/null | awk '{printf "%d", $1*1000}')" total_ms=$((total_ms + ms)) done AVG_MS=$((total_ms / 20)) RPS=$((1000 / (AVG_MS + 1))) P99="$AVG_MS" fi PASS="true" [ "$RPS" -lt "$pass_rps" ] && PASS="false" [ "$P99" -gt "$pass_p99_ms" ] && PASS="false" printf ' RPS: %s (min %s) | P99: %sms (max %sms) | %s\n' \ "$RPS" "$pass_rps" "$P99" "$pass_p99_ms" "$( [ "$PASS" = "true" ] && printf 'PASS' || printf 'FAIL')" printf '{"name":"%s","url":"%s","rps":%s,"p99_ms":%s,"target_rps":%s,"target_p99_ms":%s,"pass":%s}' \ "$name" "$url" "$RPS" "$P99" "$pass_rps" "$pass_p99_ms" "$PASS" } RESULTS=() RESULTS+=("$(bench_http "tenant-api-health" "$BASE_URL/actuator/health" 5 50 20 1000)") if printf '%s' "$PROFILE" | grep -q 'im' && [ -n "${IM_DOMAIN:-}" ]; then RESULTS+=("$(bench_http "im-api-health" "${IM_DOMAIN}/actuator/health" 5 50 20 1000)") fi if printf '%s' "$PROFILE" | grep -q 'update' && [ -n "${UPDATE_DOMAIN:-}" ]; then RESULTS+=("$(bench_http "update-api-health" "${UPDATE_DOMAIN}/actuator/health" 5 50 20 1000)") fi # Docker stats snapshot DOCKER_STATS="$(docker stats --no-stream --format '{"container":"{{.Name}}","cpu":"{{.CPUPerc}}","mem":"{{.MemUsage}}"}' 2>/dev/null || echo '[]')" RESULTS_JSON="$(printf '%s\n' "${RESULTS[@]}" | paste -sd ',' - | sed 's/^/[/' | sed 's/$/]/')" cat > "$REPORT_FILE" <