Skip to content

메트릭 태그 키셋 정합성 통일 및 등록 팩토리 도입 (ai.client.calls · async.task.failures) - #261

Merged
ckdals4600 merged 1 commit into
mainfrom
feature/#259-unify-aiclientcalls
Jul 27, 2026
Merged

메트릭 태그 키셋 정합성 통일 및 등록 팩토리 도입 (ai.client.calls · async.task.failures)#261
ckdals4600 merged 1 commit into
mainfrom
feature/#259-unify-aiclientcalls

Conversation

@ckdals4600

@ckdals4600 ckdals4600 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

관련 이슈

PR 설명

동일한 메트릭 이름을 여러 지점에서 등록하는데 태그 키셋이 일치하지 않는 문제를 교정하고, 재발을 구조적으로 차단하기 위해 메트릭 등록 전용 팩토리를 도입했습니다. (#256 PR 리뷰에서 도출)

배경

  • ai.client.calls: RagAnswerClientoperation 태그 없이 client·result 로 등록되어, 같은 메트릭을 쓰는 나머지 클라이언트(client·operation·result)와 키셋이 갈렸습니다.
  • async.task.failures: LinkSyncEventListenertask·action, 나머지(SummaryWorker, LinkEventListener)는 task 만 사용해 키셋이 갈렸습니다.
  • 같은 메트릭 이름에 서로 다른 태그 키셋이 등록되면 등록 충돌·집계 오류 위험이 있고, async.task.failures 는 이미 관측 레이어까지 오염된 상태였습니다 — 알림 룰 description 이 {{ if $labels.action }} 조건문으로 태그 유무를 방어하고 있었고, 대시보드의 sum by (task, action) 패널에서 action 없는 시계열은 빈 라벨로 표시됐습니다.
  • 같은 결함이 두 메트릭에서 연달아 발생한 것은 메트릭 등록 방식에 강제 장치가 없다는 구조적 신호로 판단했습니다.

변경 사항

1. ai.client.calls — 키셋을 client·operation·result 로 통일

  • RagAnswerClientoperation=generate 추가 (나머지 클라이언트는 이미 정합)

2. async.task.failures — 키셋을 task·action 으로 통일

  • task(작업 계열)와 action(그 안의 동작)은 의미가 다른 차원이므로 문자열로 뭉치지 않고 2차원 라벨로 정렬했습니다.
등록 위치 변경 전 변경 후
SummaryWorker task=summary-generate task=summary, action=GENERATE
LinkEventListener task=summary-enqueue task=summary, action=ENQUEUE
LinkSyncEventListener task=link-sync, action=CREATE/UPDATE/DELETE 변경 없음

3. 메트릭 등록 팩토리 도입 (재발 방지)

  • AiClientMetrics.counter(registry, Client, Operation, Result) / AsyncTaskMetrics.failureCounter(registry, Task, Action) 를 추가하고, 7개 등록 지점 전부를 팩토리 경유로 전환했습니다.
  • 태그 키셋을 메서드 시그니처로 고정하여 키셋 누락·추가가 컴파일 단계에서 불가능합니다. 태그 값도 enum 으로 고정해 오타·표기 흔들림을 막았습니다.
  • 부수 효과로, 메트릭 태그와 구조화 로그(ExternalApiLogger)의 client=/operation= 값이 같은 enum 에서 나와 자동으로 일치합니다.

4. 관측 레이어 정합

  • 알림 룰 AsyncTaskFinalFailure: action 이 항상 존재하게 되어 {{ if $labels.action }} 조건 분기를 제거하고 summary/description 에 action 을 무조건 표기.
  • Grafana AI/Async 대시보드 패널 4: sum by (task)sum by (task, action), legend {{task}} / {{action}} 로 변경 (패널 5는 기존 쿼리 유지).

5. 값 도메인에 대한 의도적 결정 — link-sync 에 empty 미추가

  • RagLinkSyncClientvoid 반환이라 '빈 응답' 결과가 도메인에 존재하지 않으므로, result 값은 success/failure 2종만 사용합니다(코드 주석으로 명시).
  • 통일 대상은 태그 키셋이며, 태그 의 도메인은 각 대상의 성격에 따라 다를 수 있습니다. 존재하지 않는 결과를 0으로 등록하면 지표가 도메인을 왜곡하고, 실패율 알림 룰도 link-sync 분모가 success+failure 로 정상 계산되므로 왜곡이 없습니다.
  • 관측성 기본선 구축: health/readiness/liveness/metrics #239 의 "카운터 0 선등록" 원칙은 발생 가능하지만 아직 안 일어난 결과의 시계열을 미리 만드는 취지이며, 발생 자체가 불가능한 결과를 만드는 것이 아닙니다.

6. 테스트

  • MetricsTagConsistencyTest 추가: 두 팩토리의 모든 enum 조합을 등록해 태그 키셋이 단일 키셋으로 수렴하는지, 동일 태그 재등록 시 같은 미터가 반환되는지 검증합니다. 팩토리를 우회하지 않는 한 키셋 일탈이 테스트로 차단됩니다.

참고

  • 코드 내 설명 주석은 main 머지 시 전부 삭제할 예정입니다. 설계 의도(팩토리의 키셋 강제, link-sync empty 미추가 근거 등)는 본 PR 본문을 기록으로 남깁니다.
  • Counter.builder 직접 호출 금지를 아키텍처 테스트(ArchUnit)로 강제하는 것은 후속 이슈로 분리합니다.
  • async.task.failures 의 기존 task 값이 변경되어 Prometheus 기존 시계열과 단절됩니다. 운영 초기이므로 지금 바로잡는 비용이 가장 낮다고 판단했습니다.

@ckdals4600
ckdals4600 requested a review from Goder-0 July 16, 2026 16:27
@ckdals4600 ckdals4600 self-assigned this Jul 16, 2026
@ckdals4600 ckdals4600 linked an issue Jul 16, 2026 that may be closed by this pull request
@ckdals4600
ckdals4600 force-pushed the feature/#259-unify-aiclientcalls branch 4 times, most recently from 13ecb32 to 3415c75 Compare July 16, 2026 17:11
@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown

📊 코드 커버리지 리포트

Overall Project 93.83% 🍏
Files changed 100% 🍏

File Coverage
LinkEventListener.java 100% 🍏
LinkSyncEventListener.java 100% 🍏
RagSummaryClient.java 100% 🍏
AiClientMetrics.java 100% 🍏
AsyncTaskMetrics.java 100% 🍏
RagAnswerClient.java 100% 🍏
SummaryWorker.java 97.72% 🍏
RagTitleClient.java 94.05% 🍏
RagLinkSyncClient.java 89.29% 🍏

동일 메트릭 이름에 태그 키셋이 갈리는 문제를 교정하고 재발을 구조적으로 차단.

- ai.client.calls: RagAnswerClient 에 operation=generate 추가로
  4개 클라이언트 전부 client·operation·result 키셋으로 통일
- async.task.failures: task(계열)·action(동작) 2차원으로 정렬
  (summary-generate → summary/GENERATE, summary-enqueue → summary/ENQUEUE)
- 등록 팩토리 도입(AiClientMetrics, AsyncTaskMetrics): 태그 키셋을 메서드
  시그니처로 고정해 컴파일 단계 강제, 값은 enum 으로 고정
- 관측 레이어 정합: AsyncTaskFinalFailure 의 action 조건분기 제거,
  대시보드 패널4 sum by (task, action) 전환
- link-sync 는 void 반환이라 result=empty 미등록(의도적, 값 도메인은 도메인별)
- MetricsTagConsistencyTest: 전 조합 키셋 수렴 검증
@ckdals4600
ckdals4600 force-pushed the feature/#259-unify-aiclientcalls branch from 89adb22 to dbcbc46 Compare July 27, 2026 13:48
@ckdals4600
ckdals4600 merged commit 0088716 into main Jul 27, 2026
2 checks passed
@ckdals4600
ckdals4600 deleted the feature/#259-unify-aiclientcalls branch July 27, 2026 13:49
ckdals4600 added a commit that referenced this pull request Jul 27, 2026
Counter.builder 직접 호출을 global.metrics 패키지 외부에서 금지하는
ArchUnit 규칙 추가. 팩토리(#261)를 우회한 등록이 컴파일·기존 테스트를
통과하며 태그 키셋 불일치를 재발시키는 것을 구조적으로 차단.

- archunit-junit5 의존성 추가 (testImplementation)
- 규칙은 main 코드만 검사 (DoNotIncludeTests)
ckdals4600 added a commit that referenced this pull request Jul 27, 2026
Counter.builder 직접 호출을 global.metrics 패키지 외부에서 금지하는
ArchUnit 규칙 추가. 팩토리(#261)를 우회한 등록이 컴파일·기존 테스트를
통과하며 태그 키셋 불일치를 재발시키는 것을 구조적으로 차단.

- archunit-junit5 의존성 추가 (testImplementation)
- 규칙은 main 코드만 검사 (DoNotIncludeTests)
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.

메트릭 태그 키셋 정합성 통일 및 등록 팩토리 도입

2 participants