Skip to content

feat(metrics): 동시 접속자 게이지 active_users 추가 - #76

Merged
weeast1521 merged 1 commit into
mainfrom
feat/active-user-metrics
Oct 23, 2026
Merged

weeast1521 merged 1 commit into
mainfrom
feat/active-user-metrics

Conversation

@weeast1521

@weeast1521 weeast1521 commented Oct 23, 2026 •

Copy link
Copy Markdown
Owner

📍 PR 타입 (하나 이상 선택)

  • 기능 추가
  • 버그 수정
  • 의존성, 환경 변수, 빌드 관련 코드 업데이트
  • 기타 사소한 수정

🏷️ 관련 이슈

Close #

📌 개요

  • "지금 접속자가 몇 명인가"에 답하는 게이지 active_users{window="1m|5m"} 추가 — 최근 N분 안에 활동한 고유 사용자 수
  • 기존 지표로는 답할 수 없었다
    • websocket_sessions는 대전 방에 입장한 사람만 센다 (프론트가 방 입장 때만 WebSocket을 연다)
    • 솔로 시작 요청 수는 보드 재시작이 중복으로 잡히고, 랭킹만 보는 사람은 빠진다
    • 실제로 10-23 13:30 경 대전 세션은 23이었지만 솔로 시작은 2분당 3058회였다

🔁 변경 사항

  • ActiveUserTracker (신규, global/metrics): userId별 마지막 활동 시각을 인메모리 맵에 기록하고 MeterBinder로 게이지 등록. 게이지를 읽을 때(15초마다) 30분 넘게 조용한 항목을 정리한다 — 스케줄러 없음
  • JwtAuthenticationFilter: 인증 성공 직후 touch(userId) — 인증된 모든 HTTP가 지나는 자리라 컨트롤러마다 심지 않아도 된다
  • StompAuthChannelInterceptor: CONNECT 이후 Principal이 붙은 모든 프레임에서 touch — 대전 중인 사람은 HTTP를 거의 안 보내서 필터만으로는 5분 창에서 빠진다
  • 대시보드 applegame-load.json
    • "한눈에" 줄 맨 앞에 활성 사용자 (5분) 타일 (기존 4타일 폭 조정)
    • 기존 "WebSocket 세션" → 대전 방 WebSocket 세션으로 이름·설명 명확화
    • 새 행 접속자 — 누가 얼마나 있나: 활성 사용자 1m/5m 추이, 솔로 시작/제출 2분 창. 아래 행들은 y +9
    • 솔로 시작 API는 201이라 상태 코드는 status=~"2.."로 건다 (200만 세면 0이 나온다)
  • docs/INFRA.md Phase 3에 10-23 2차로 기록

📸 스크린샷

머지·배포 후 "활성 사용자 (5분)" 타일과 "접속자" 행 확인 예정

✅ 체크리스트

  • 코드가 정상적으로 동작하는지 확인 — 단위 테스트 14건 통과, 대시보드 JSON 패널 겹침·24칸 초과 없음 검사
  • PR에 적절한 라벨을 선택
  • 관련 테스트 코드 작성 — ActiveUserTrackerTest 5건(중복 제거, 1m/5m 창 독립 만료, 재활동 복귀, null 무시, 게이지 노출), JwtAuthenticationFilterTest +1, StompAuthChannelInterceptorTest +1
  • 문서(README, Swagger 등) 업데이트 — docs/INFRA.md

💡 추가 사항 (리뷰어가 참고해야 할 것)

  • 인스턴스 단위 인메모리다. blue/green은 한 색만 트래픽을 받으므로 지금은 문제 없고, 전환 직후 5분은 새 색의 값이 낮게 시작한다. 수평 확장 시 Redis로 옮긴다.
  • 반영은 두 단계: ① 머지 → CI가 이미지 빌드·blue-green 배포 (게이지는 앱 코드) ② VM에서 git pull → Grafana가 30초 안에 대시보드 파일을 다시 읽는다 (updateIntervalSeconds: 30)

🤖 Generated with Claude Code

websocket_sessions는 대전 방에 입장한 사람만 세고(프론트가 방 입장 때만
WebSocket을 연다), 솔로 시작 요청 수는 보드 재시작이 중복으로 잡혀 접속자
수로 쓸 수 없었다. 인증을 통과한 지점에서 userId별 마지막 활동 시각을
기록하고 "최근 1분/5분 안에 활동한 고유 사용자 수"를 게이지로 노출한다.

- ActiveUserTracker: 인메모리 Map<userId, lastSeen>, MeterBinder로
  active_users{window="1m|5m"} 등록. 게이지 읽을 때 30분 넘은 항목 정리.
- JwtAuthenticationFilter: 인증 성공 시 touch — 인증된 모든 HTTP가 지나는 곳.
- StompAuthChannelInterceptor: CONNECT 이후 Principal이 붙은 모든 프레임에서
  touch — 대전 중인 사람은 HTTP를 거의 안 보내서 필터만으로는 창에서 빠진다.
- 대시보드: "활성 사용자 (5분)" 타일, "접속자" 행(활성 사용자 1m/5m 추이,
  솔로 시작/제출 2분 창). 솔로 시작은 201이라 status=~"2.."로 건다.
- 테스트: 창별 만료·중복 제거·게이지 노출, 필터·인터셉터의 기록 여부.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@weeast1521
weeast1521 merged commit f215d2e into main Oct 23, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant