#!/usr/bin/env bash # # PostgreSQL 커넥션 모니터 (로그 방식). negosium_db 커넥션을 한 줄씩 쌓아가며 본다. # 부하테스트(run_local_locust.sh) 중 별도 터미널에서 띄워 풀 사용량 추세를 관찰한다. # (화면을 덮어쓰지 않으므로 스크롤로 이력을 그대로 볼 수 있다) # set -uo pipefail cd "$(dirname "$0")" # backend/ # DB 접속 (local 기본값, 환경변수로 override 가능) PGHOST="${PGHOST:-127.0.0.1}" PGPORT="${PGPORT:-5432}" PGUSER="${PGUSER:-postgres}" PGDATABASE="${PGDATABASE:-negosium_db}" q() { psql -h "$PGHOST" -p "$PGPORT" -U "$PGUSER" -d "$PGDATABASE" "$@"; } # 접속 확인 if ! q -tAc "SELECT 1" >/dev/null 2>&1; then echo "[error] DB 접속 실패: $PGUSER@$PGHOST:$PGPORT/$PGDATABASE" exit 1 fi MAXCONN="$(q -tAc "SHOW max_connections;" 2>/dev/null | tr -d '[:space:]')" MAXCONN="${MAXCONN:-0}" read -rp "갱신 간격(초) [1]: " ITV; ITV="${ITV:-1}" read -rp "로그 파일로도 저장 (경로, 비우면 화면만): " LOGF echo "DB=$PGDATABASE max_connections=$MAXCONN (Ctrl+C 로 종료)" echo " - total: 전체 커넥션 / active: 실행 중 / idle: 풀 유휴 / idle_tx: 트랜잭션 유휴(누수 의심)" HEADER="시각 total active idle idle_tx" echo "$HEADER" [[ -n "$LOGF" ]] && { echo "# $HEADER" >>"$LOGF"; } emit() { # 화면 + (옵션)파일 echo "$1" [[ -n "$LOGF" ]] && echo "$1" >>"$LOGF" } # 우리 앱 풀 산식(참고): USER/PARTNER × R/W = 엔진 4벌 × (pool_size+max_overflow) = 최대 120 / 워커 while true; do TS="$(date '+%H:%M:%S')" # 상태별 카운트를 한 쿼리로(모니터 자신은 제외). 출력: "total active idle idle_tx" ROW="$(q -tAF' ' -c "SELECT count(*), count(*) FILTER (WHERE state='active'), count(*) FILTER (WHERE state='idle'), count(*) FILTER (WHERE state='idle in transaction') FROM pg_stat_activity WHERE datname='$PGDATABASE' AND pid <> pg_backend_pid();" 2>/dev/null)" read -r TOTAL ACTIVE IDLE IDLETX <<<"${ROW:-0 0 0 0}" TOTAL="${TOTAL:-0}"; ACTIVE="${ACTIVE:-0}"; IDLE="${IDLE:-0}"; IDLETX="${IDLETX:-0}" PCT=0 if [[ "$MAXCONN" =~ ^[0-9]+$ && "$MAXCONN" -gt 0 ]]; then PCT=$(( TOTAL * 100 / MAXCONN )); fi WARN="" if (( PCT >= 80 )); then WARN=" <- max 임박!"; fi emit "$(printf '%s %3s/%s (%3s%%) %5s %4s %4s%s' \ "$TS" "$TOTAL" "$MAXCONN" "$PCT" "$ACTIVE" "$IDLE" "$IDLETX" "$WARN")" sleep "$ITV" done