Skip to content

[improve/#64] Gemini 사용량 및 요청 로그 진단 보강#65

Merged
Yujin1219 merged 6 commits into
developfrom
improve/wantkdd-logging-diagnostics#64
Jun 1, 2026
Merged

[improve/#64] Gemini 사용량 및 요청 로그 진단 보강#65
Yujin1219 merged 6 commits into
developfrom
improve/wantkdd-logging-diagnostics#64

Conversation

@wantkdd
Copy link
Copy Markdown
Collaborator

@wantkdd wantkdd commented Jun 1, 2026

✨ 작업 개요

Gemini 호출 비용/실패 원인을 운영 로그에서 추적할 수 있도록 usage metadata와 요청 body 진단 로그를 보강했습니다.

📄 작업 내용

  • Gemini generate_content 응답의 usage metadata를 구조화 로그로 기록하도록 추가했습니다.
  • 요청 body 로깅 시 토큰/비밀번호류 민감정보, 발화 원문, diff 본문, multipart 파일 원문이 그대로 남지 않도록 마스킹/요약 처리했습니다.
  • 전사 보정 Gemini 호출에 segment 수와 화자 수 context를 함께 기록하도록 했습니다.
  • Gemini usage 로그와 요청 body 마스킹/요약 동작에 대한 회귀 테스트를 추가했습니다.

📌 관련 이슈

🔌 API 변경사항 (해당 시)

  • 없음

💬 기타 사항

  • 요청/응답 스키마 변경은 없습니다.
  • 운영 로그에는 원문 발화나 변경 코드 전체 대신 길이 요약과 집계 context만 남도록 했습니다.
  • 검증: uv run pytest 110 passed, uv run ruff check 통과

Summary by CodeRabbit

릴리스 노트

  • 새 기능

    • API 호출 사용량 메타데이터(토큰 수 등)를 구조화된 로그로 기록
  • 보안 강화

    • 요청 로그에서 토큰, 패스워드, 인증 정보 등 민감 데이터 자동 마스킹
  • 테스트

    • 로깅 및 데이터 마스킹 기능 검증 테스트 추가

wantkdd added 5 commits June 1, 2026 19:12
Constraint: 운영에서 토큰 사용량 급증 원인을 원문 없이 확인해야 함
Confidence: high
Scope-risk: narrow
Directive: Gemini 호출 추가 시 generate_content_with_retry를 경유해 usage 로그를 유지할 것
Tested: uv run pytest tests/test_logging_middleware.py tests/test_gemini_retry.py; uv run ruff check targeted files
Not-tested: 실제 Gemini API 과금 대시보드 반영 지연
Constraint: usage metadata 로그는 비용 추적 근거라 회귀 테스트가 필요함
Confidence: high
Scope-risk: narrow
Directive: usage 로그 필드명을 바꿀 때 테스트 기대 문자열도 함께 갱신할 것
Tested: uv run pytest tests/test_logging_middleware.py tests/test_gemini_retry.py; uv run ruff check targeted files
Not-tested: 실제 외부 Gemini 응답 객체 전체 필드 변형
Constraint: 운영 로그에서 diff, 발화 원문, 토큰류 비밀이 그대로 노출되면 안 됨
Rejected: 전체 body 원문 로깅 | 민감정보와 긴 diff가 로그 파일에 남을 수 있음
Confidence: high
Scope-risk: moderate
Directive: 새 요청 필드에 원문/비밀이 담기면 _SENSITIVE_KEY_PARTS 또는 _VERBOSE_KEY_PARTS에 추가할 것
Tested: uv run pytest tests/test_logging_middleware.py tests/test_gemini_retry.py; uv run ruff check targeted files
Not-tested: 외부 로그 수집기에서의 필드별 인덱싱 동작
Constraint: 로깅 미들웨어는 운영 진단용이면서 개인정보와 비밀을 남기면 안 됨
Confidence: high
Scope-risk: narrow
Directive: body 로깅 정책을 바꿀 때 JSON, multipart, request body 재사용 테스트를 유지할 것
Tested: uv run pytest tests/test_logging_middleware.py tests/test_gemini_retry.py; uv run ruff check targeted files
Not-tested: 대용량 실제 오디오 업로드 전체 경로
Constraint: 전사 보정 비용과 실패 원인을 segment 수와 화자 수 기준으로 추적해야 함
Confidence: high
Scope-risk: narrow
Directive: 전사 보정 입력 원문은 로그에 남기지 말고 집계 맥락만 남길 것
Tested: uv run pytest tests/test_logging_middleware.py tests/test_gemini_retry.py; uv run ruff check targeted files
Not-tested: 운영 회의 녹음 기반 실제 전사 보정 호출
@wantkdd wantkdd self-assigned this Jun 1, 2026
@wantkdd wantkdd requested a review from Yujin1219 June 1, 2026 10:16
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 1, 2026

Review Change Stack

Warning

Review limit reached

@wantkdd, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 36 minutes and 27 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 079c3680-ce0e-43e3-880a-e63d6132e28c

📥 Commits

Reviewing files that changed from the base of the PR and between fe8b82e and ea6c726.

📒 Files selected for processing (2)
  • app/core/logging_middleware.py
  • tests/test_logging_middleware.py
📝 Walkthrough

Walkthrough

이 PR은 Gemini API 호출 사용량과 API 요청 본문을 진단 목적으로 안전하게 로깅하는 기능을 추가합니다. usage_metadata 구조화 로깅, 요청 본문 민감정보 마스킹, 전사 보정 서비스 컨텍스트 메타데이터 기록이 구현되었습니다.

Changes

Logging Instrumentation for Gemini & Requests

Layer / File(s) Summary
Gemini usage logging utilities and tests
app/core/gemini.py, tests/test_gemini_retry.py
_usage_value 헬퍼와 log_gemini_usage 함수가 Gemini 응답의 usage_metadata에서 토큰 카운트를 추출하고 구조화된 정보로 로깅합니다. generate_content_with_retrylog_context 파라미터를 추가하여 호출 후 usage를 자동으로 기록하고, 비동기 테스트가 로그 출력을 검증합니다.
Request body sanitization and middleware logging
app/core/logging_middleware.py, tests/test_logging_middleware.py
요청 본문의 민감 키(토큰, 패스워드, authorization)를 <masked>로 치환하고, 긴 필드는 문자 수로 요약, 배열은 항목 개수를 제한하는 _sanitize_json 로직이 추가됩니다. _format_body_for_log는 JSON 파싱 실패 시 malformed 표기와 multipart 요청 시 바이너리 콘텐츠 노출 방지를 처리하며, RequestLoggingMiddleware에서 요청을 소비하지 않으면서 마스킹된 본문을 로깅합니다. 3개의 테스트가 마스킹, 요청 소비 방지, multipart 처리를 검증합니다.
Transcript correction context logging
app/domains/transcribe/services/transcript_correction.py
correct_transcript의 Gemini 호출에 log_context를 추가하여 세그먼트 개수(segment_count)와 화자 수(num_speakers)를 메타데이터로 전달하므로, 후처리 실행 시 운영 환경에서 처리 규모를 추적할 수 있습니다.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • WhyLog-App/Whylog-AI#51: 공통 generate_content_with_retry 함수의 재시도 로직 기반 위에서 log_context 및 usage 로깅 흐름을 확장하는 직접적 선행 변경입니다.

Suggested labels

🛠 Fix

Suggested reviewers

  • Yujin1219

Poem

🐰 토큰 계산 로그 남기고
🔐 민감한 값은 안전하게 마스킹하고
📊 요청 흐름 추적하는 모습,
운영 안목을 밝혀주네! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.76% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 주요 변경사항(Gemini 사용량 및 요청 로그 진단 보강)을 명확하게 요약하고 있으며, 변경사항과 완벽하게 관련되어 있습니다.
Description check ✅ Passed PR 설명이 템플릿의 모든 필수 섹션(작업 개요, 작업 내용, 관련 이슈, 기타 사항)을 포함하고 있으며, 각 섹션이 구체적이고 완성도 높게 작성되었습니다.
Linked Issues check ✅ Passed 코드 변경이 #64의 모든 주요 목표를 충족합니다: Gemini usage metadata 구조화 로그 추가, 요청 body의 민감정보 마스킹/요약 처리, context 로그 강화, multipart 원문 로깅 방지, 전사 보정 호출에 segment/화자 수 context 기록, 관련 테스트 추가.
Out of Scope Changes check ✅ Passed 모든 변경사항이 #64의 범위 내에 있으며, 요구된 Gemini 로깅, 요청 body 마스킹, context 로그 강화, 테스트 추가 외에 벗어난 변경사항은 없습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch improve/wantkdd-logging-diagnostics#64

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@wantkdd wantkdd added the 🚀 Feat 기능 구현 및 수정 label Jun 1, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/core/logging_middleware.py`:
- Around line 106-117: The handler currently decodes and logs any UTF-8 body
when content_type doesn't contain "application/json"; change the logic to treat
any content_type containing "+json" or "application/json" as JSON (so pass
through json.loads -> _sanitize_json -> _truncate via existing code paths) and
for all other content types avoid returning raw body_text — instead return a
safe placeholder like "(omitted body, content_type={content_type},
content_length={len(body_bytes)})" or a short summary/omitted string using
_truncate; update the branch that uses content_type and body_bytes and keep
using _sanitize_json and _truncate for JSON variants; add regression tests that
assert application/x-www-form-urlencoded and text/plain do not return raw
sensitive fields and that application/*+json is sanitized via _sanitize_json.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 7d856152-81d1-4167-a0df-18d11b4b95f2

📥 Commits

Reviewing files that changed from the base of the PR and between 22597d7 and fe8b82e.

📒 Files selected for processing (5)
  • app/core/gemini.py
  • app/core/logging_middleware.py
  • app/domains/transcribe/services/transcript_correction.py
  • tests/test_gemini_retry.py
  • tests/test_logging_middleware.py

Comment thread app/core/logging_middleware.py Outdated
Constraint: text/plain과 form-urlencoded 본문에도 비밀 값이 포함될 수 있음
Rejected: UTF-8 본문 원문 로깅 | JSON 외 요청의 password/token 값이 로그에 남을 수 있음
Confidence: high
Scope-risk: narrow
Directive: JSON 계열은 +json까지 sanitize하고 그 외 body는 길이 요약만 남길 것
Tested: uv run pytest; uv run ruff check
Not-tested: 실제 외부 프록시가 변형한 content-type 조합
Copy link
Copy Markdown
Member

@Yujin1219 Yujin1219 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

굿

@Yujin1219 Yujin1219 merged commit bf510d2 into develop Jun 1, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🚀 Feat 기능 구현 및 수정

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[improve] Gemini 사용량 및 요청 로그 진단 보강

2 participants