기존 buffer/uploader 유지
최소 문맥과 진단 이벤트
S3 진단 로깅 개선
적용 계획
마지막 업데이트 2026-09-08
web · socket · LiveKit에서 사건의 시작, 실패 원인, 복구 결과를 연결하고 반복 로그를 줄인다.
P0-1(LiveKit 오류·프롬프트 상태)과 P0-2(삭제·생성 감사)는 구현됐다 — PR #1071 커밋 리뷰. P0-3(서버 → S3 수집 경로), P1(전환·ACK·미디어), 4장의 로그 축소는 미착수다. 배포는 아직이다.
구현 과정에서 아래 1장·2장의 전제 3개가 실제 코드와 다른 것으로 확인됐다. 후속 작업 시 이 문서보다 PR 리뷰 문서를 신뢰한다.
- 마스킹:
dbb120fc(PPI-1273, 9/4)로 이미 자격증명 key만 가리도록 축소됨. 9/3~9/6 보고서의[REDACTED]는 그 커밋 전 로그이므로 범위에서 제외했다. - 프롬프트 fingerprint: 신규 수집이 아니라
build_safe_model_config_log_payload와livekit-session-config-store.ts에 이미 있었고 호출만 안 되고 있었다. AUTO_TRANSITION|stepUpdate: web 소스에 없는 문자열이며 분석기 라벨이다. 실제 경로는video-end-watchdog.ts→guest-step-publisher.ts이고 후자에는 revision·ack·retry가 이미 있다.
또한 3장이 제안한 이벤트 이름 대신 기존 boundary/outcome/error_class 규약을 재사용했고(신규 API·S3 prefix 없음), error_message 원문은 lifecycle_trace.py의 기존 계약을 따라 수집하지 않는다.
1. 현재 상황과 확인 한계
| 항목 | 확인된 사실 | 의미·추가 확인 |
|---|---|---|
| 브라우저 수집 | logger.js → lesson-log-sink → buffer → uploader. 직접 console 호출은 warn/error를 수집한다. 기본 최소 레벨은 debug, 업로드 기본값은 OFF이며 서버 설정과 개발용 override가 적용된다. | 운영 실제 설정은 별도 확인 필요. 서버 로그가 이 경로로 자동 수집되는 구조는 아니다. |
| LiveKit 내부 오류 | agent.py에는 상태·전사 이벤트 전달이 있지만 일반 AgentSession error 이벤트 구독은 조사한 파일에서 확인되지 않았다. 지침은 config에서 읽어 Agent에 넘긴다. | 사용자 보고: 토큰 초과 후 빈 프롬프트 AI 세션 생성. SDK 오류가 어디서 발생·흡수되는지, 지침이 실제로 비었는지는 재현과 원본 오류로 검증해야 한다. |
| 템플릿 삭제 | 삭제 API는 템플릿 조회 후 삭제하고 success를 반환한다. 성공 감사 로그가 없다. buildActivitiesFromTemplate은 누락 참조가 있으면 ACTIVITY_TEMPLATE_NOT_FOUND를 던진다. | 삭제자·삭제 시점과 이후 생성 실패를 연결할 기록이 필요하다. 누락만으로 삭제를 단정하지 않는다. |
| 수업 이전 사건 | 기존 append API는 guest/monitor 역할과 기존 회기를 요구한다. | 템플릿 삭제와 아직 생성되지 않은 회기의 실패는 별도 서버 감사 로그 경로가 필요하다. |
| 마스킹 | 공통 logger는 token을 포함한 key를 비밀값으로 가린다. Error 직렬화는 name/message/stack을 보존한다. | 사용량·한도 수치가 사라질 수 있고, provider code/status는 명시 추출이 필요하다. 보고서의 REDACTED 원인이 현재 sanitizer라고 단정하지 않는다. |
최근 Daily Reports에서 드러난 진단 과제
- 9월 1일: 244개 중 후보 62개. input enabled RPC 오류가 client와 AI_SESSION에 함께 등장하며 consumer resume, 늦은 RPC ACK, 영상 seek/rebuffer가 보인다.
- 9월 2일: 후보 50/247개. 연결 오류, 재입장 루프, 리소스 실패와 RPC 응답 문제가 포함된다.
- 9월 3일, 9월 4일, 9월 5일, 9월 6일: GUEST_STEP_UTILS 등에서
[REDACTED]시그니처가 반복되어 원인을 구분하기 어렵다. - 9월 7일: 223개 세션 모두 자동전환 긴급 후보. 대표 시그니처는
AUTO_TRANSITION|stepUpdate이며 nearEndFallback/watchdogBackstop 뒤 서버 반영 부재로 서술된다.
보고서는 후보 선별 자료다. 전 세션 실제 장애, 정상 fallback의 오탐, 또는 분석기의 상관관계 실패 중 어느 것인지는 미확정이다. 해당 AUTO_TRANSITION 문구는 현재 조사한 web 소스에서 찾지 못했으므로 배포 revision과 보고서 생성 규칙도 대조한다. 운영 S3 원본을 이번 문서 작성에서 직접 분석하지 않았다.
2. 적용 범위
| 우선순위·대상 | 추가·보강 | 주요 적용 파일·경계 |
|---|---|---|
| P0 · LiveKit | 세션 시작·오류·종료 결과, provider 오류 code/type/status/recoverable, 초기 구성/업데이트/응답 생성 단계, 프롬프트 길이·빈 값 여부·안전한 fingerprint·버전. 토큰 수치는 출처와 실제/추정 구분. | apps/livekit-agent/agent.pyapps/web/lib/voice-agent/livekit-client-session.ts모델 config 생산자·SDK 내부 오류 경계는 구현 전 추가 추적 |
| P0 · 삭제·생성 | 삭제 요청·성공·실패, 인증된 작업자 ID·template ID, 회기 생성 요청 ID·lesson template ID·누락 ID 목록·실패 단계·최종 결과. 부분 저장이 있으면 그 결과도 구분. | apps/web/app/api/activity-templates/[id]/route.tsapps/web/app/api/lessons/route.tsapps/web/lib/lesson-utils.tsapps/web/lib/db-queries.ts |
| P0 · S3 수집·공통 계약 | 서버 직접 저장 경로, 수업 이전 감사 기록, source/schemaVersion/eventId, 허용 필드 기반 오류 정규화, 누락·업로드 실패 요약. | apps/web/lib/lesson-log-*.tsapps/web/hooks/use-lesson-log-uploader.tsapps/web/app/api/lesson-logs/*apps/web/lib/s3.tspackages/shared/src/utils/logger.ts |
| P1 · 전환·socket | 동일 transition ID/revision으로 요청·서버 수신·반영·ACK·재시도·최종 실패를 연결. 오래된 revision, 중복, 정상 종료와 실제 미반영 구분. | apps/web/lib/guest-step-utils.tsapps/web/lib/guest-step-publisher.tsapps/socket/src/sfu-socket/handlers/session-diagnostic-handlers.ts실제 스텝 반영 handler와 호출자는 추가 추적 |
| P1 · AI 입력·미디어·리소스 | RPC 요청과 최종 결과, consumer/transport 상태, 재접속·복구 결과, 리소스 실패 종류. 정상 종료·복구와 진행 중 장애를 구별할 최소 상태 보존. | LiveKit client session, socket transport/session 경계, 미디어·리소스 오류 발생 지점. 최근 보고서 시그니처와 원본을 매핑한 뒤 파일 확정. |
경계: 로깅 개선은 guardian combined 작업이다. 서버 수집 경로와 공통 계약 확장은 architectural 설계로 다룬다. 자동 프롬프트 축약, 빈 프롬프트 세션 차단 정책, 템플릿 삭제 차단·복원, ACK 동작·재시도 횟수 변경은 이 계획의 로깅 변경과 분리한다. UI 변경은 기본 범위에 없으며 필요해지면 별도 설계와 Storybook 검증을 추가한다.
3. S3 전달 설계 제안
인증된 서버 수집 경계
브라우저 없이도 오류 전달
수업 로그 + 수업 이전 감사 로그
eventId·entity ID로 연결
기존 LiveKit data channel relay는 브라우저 진단에 재사용하되, 초기화 실패나 브라우저 미접속 오류를 보존하는 유일한 경로로 삼지 않는다. 권장안은 기존 web 서버 S3 writer를 재사용하는 서버 전용 수집 경계이며 socket/Agent가 서비스 인증으로 전달한다. 현재 guest/monitor 인증을 서버 역할로 우회하지 않는다.
- 저장 계약:
schemaVersion, eventId, event, ts, source, level, stage, outcome, reasonCode와 요청/회기/활동/시도 식별자를 필요할 때만 포함한다. 기존ts/level/ctx/msg/data소비자와 호환되는 직렬화·merge 검증을 먼저 한다. - 상관관계: 회기 사건은 userId/lessonIndex와 session/attempt ID로 묶고, 삭제 사건은 template ID와 request ID를 사용한다. 삭제와 나중의 생성 실패는 공통 template ID 및 시각으로 연결한다. 한 request ID를 서로 다른 작업에 재사용하지 않는다.
- 저장 위치: 수업 사건은 기존 lesson-logs 계열을 우선 재사용한다. 수업 이전 사건은 별도 audit prefix 제안. key 형식·권한·보존 기간은 현재 인프라 정책 확인 후 설계에서 확정한다. 새 경로는 회기 존재 검사를 요구하지 않는다.
- 신뢰 경계: 작업자는 서버 인증값으로 결정한다. 클라이언트가 보낸 actor/source를 그대로 신뢰하지 않는다. source별 허용 이벤트·필드·크기 제한과 rate limit을 적용한다.
- 실패 격리: 제한된 버퍼·재시도·종료 flush와 실패 카운터를 둔다. 로깅 실패가 수업 API 결과나 음성 처리를 바꾸지 않게 한다. 프로세스 급사까지 무손실 보장은 별도 durable queue 없이 주장하지 않는다.
- 중복 처리: 재전송은 같은 eventId를 유지한다. 직접 저장과 relay가 같은 사건을 보내면 수집/merge에서 하나의 사건으로 처리하되 source별 전달 결과는 진단 가능하게 남긴다.
사건별 결과 예시 — 이름은 제안
ai.session.failed
stage: session_start | instructions_update | response_create
reasonCode: provider가 준 code를 허용 목록으로 정규화
prompt: { charCount, byteCount, empty, version }
usage: { inputCount, limitCount, measurementSource }
template.delete.completed / template.delete.failed
lesson.create.failed → missingTemplateIds + lessonTemplateId
step.commit.completed / step.commit.failed → revision + attempts
log.delivery.summary → acceptedCount + droppedCount + retryCount응답이 주지 않은 토큰 수치·오류 코드는 만들어 넣지 않는다. 전송 성공과 모델의 지침 적용 성공을 구분하며, SDK가 적용 ACK를 노출하지 않으면 applied를 단정하지 않고 unknown을 기록한다. 프롬프트·대화 원문·인증정보는 이 계획에서 새로 수집하지 않는다. fingerprint는 원문 추정 위험과 필요성을 검토해 선택한다.
4. 불필요한 로그를 줄이는 기준
error/warn을 일괄 삭제하지 않는다. 대표 운영 로그에서 사건을 재구성한 뒤 최초 발생 + 상태 변화 + 최종 결과 + 반복 횟수를 남긴다.
| 후보 | 축소 조건 | 반드시 유지 |
|---|---|---|
| input enabled 오류의 client/AI_SESSION 중복 | 동일 요청·시도·오류임을 확인하면 대표 이벤트 하나로 통합 | 최종 실패, desired/applied 상태, 지연·재시도 수 |
| 늦은 RPC ACK·응답 | 정상 종료 또는 이미 완료된 동일 요청의 늦은 응답으로 확인된 경우 요약 | 진행 중 요청의 timeout·불일치·복구 실패 |
| consumer resume/layer 오류 | 종료된 consumer에 대한 늦은 작업임이 확인된 경우 낮은 심각도로 축약 | 활성 세션의 재생 실패·transport 단절·복구 결과 |
| 영상 waiting·seek/rebuffer, 전환 fallback | 정상 seek 또는 복구 성공으로 확인된 반복 상태 | 지속 stall, 전환 최종 미반영, ACK 재시도 소진 |
| 주기 미디어/VAD/상태 덤프 | 값 변화가 없으면 집계·샘플링, 명시적 진단 모드에서 상세 기록 | 상태 변화, 임계치 최초 초과·회복, 필요한 최소 수치 |
| force kick·운영자 조작 | 장애 카운트에서는 구분 | 원인 연결에 필요한 조작 감사 기록 |
집계 key는 event + source + session/attempt + reasonCode를 기본으로 하고 서로 다른 세션은 합치지 않는다. 초기 제안 집계 창은 30초이며 최초 사건과 최종 실패는 즉시 보존한다. 집계 창·샘플링은 대표 로그 비교 후 조정한다. 버퍼 초과 시 필수 실패 이벤트 보존 정책도 함께 검증한다.
5. 적용 순서와 산출물
- 근거 고정: 배포 revision·S3 설정·보고서 판정 규칙을 확인하고 토큰 초과, 템플릿 삭제/생성 실패, 정상 전환, 실제 전환 실패, 종료 뒤 미디어 오류의 익명화 fixture를 만든다. 산출물: 유지/삭제/축약 시그니처 목록과 근거.
- 설계 확정: 서버 인증·저장 key·이벤트 필드·상관 ID·마스킹·역호환·유실 한계를 정한다. 사용자 설계 승인 후 repository writing-plans로 테스트 우선 실행 계획을 확정한다.
- 격리 작업: 기준 브랜치를 확인하고
feat-s3-diagnostic-logging을.worktrees/feat-s3-diagnostic-logging에 생성한다. 현재 이 문서 작성 단계에서는 생성하지 않았다. - 수집 계약과 테스트: source별 인증·정규화·중복 처리·S3 저장·실패 격리 harness를 먼저 만들고 기준 테스트를 실행한다.
- P0 기록 보강: LiveKit 오류/프롬프트 상태와 템플릿 삭제·회기 생성 결과를 연결한다. SDK 오류 전파 경계는 테스트로 확인한 최소 지점만 변경한다.
- P1 정리: 전환/ACK 최종 결과와 입력·미디어 복구 상태를 보강한 뒤, 근거가 확정된 반복 로그부터 축약한다. 계측 추가와 구조 정리를 분리한다.
- 검증·리뷰·점진 배포: 관련 테스트·타입 검사, guardian-gate 리뷰를 수행한다. P0/P1은 범위 내 최대 두 번 보완하고 잔여 위험을 문서에 기록한다.
6. 수용 기준과 검증 계획
| 경우 | 통과 기준 |
|---|---|
| 토큰 초과·지침 적용 실패 | 원인 code·발생 단계·시도 ID·프롬프트 상태가 S3 payload에 남는다. SDK 내부만 출력하고 끝나지 않는다. 없는 provider 수치는 unknown/미포함으로 처리한다. |
| 브라우저 미접속 초기화 실패 | 서버 수집 경로로 오류가 저장된다. 브라우저 연결 성공이 저장 선행조건이 아니다. |
| 템플릿 삭제 후 회기 생성 실패 | 삭제자·결과와 누락 template ID를 통해 연결할 수 있다. 회기가 없어도 저장된다. DB의 기존 성공/실패 동작은 유지된다. |
| 전환·재시도 | 정상 반영, ACK 유실, 중복 요청, 오래된 revision, 실제 재시도 소진을 구분한다. 정상 복구를 최종 실패로 집계하지 않는다. |
| 축약·마스킹 | 세션 간 로그가 섞이지 않는다. 원인·첫 발생·최종 결과·횟수는 보존하고 비밀값은 차단한다. 숫자 사용량은 보존한다. |
| S3·버퍼 장애 | 재시도 중복, 저장 실패, 초과·종료 flush를 검증한다. 수업·삭제·생성 동작을 로깅 예외가 바꾸지 않는다. |
| 기존 소비자 | 기존 guest/monitor 로그의 업로드·merge·download와 신규 source를 함께 읽을 수 있다. Daily Reports가 새 이벤트를 원인·결과로 구분한다. |
기존 harness 후보: lesson-log-buffer/config/serialize/keys/merge 테스트, lesson-utils.test.ts, guest-step-publisher.test.ts, livekit-client-session 및 diagnostics 테스트, Agent pytest. 파일 존재만으로 충분하다고 간주하지 않고 위험 동작을 보호하는지 확인한다. node scripts/change-harness.mjs --files …로 후보를 좁히며 전체 테스트 대신 해당 모듈만 실행한다.
배포: 수집·이벤트 추가 → 내부/선택 세션에서 기록 확인 → 기존/신규 보고서 병렬 비교 → 반복 로그 축약 순서로 진행한다. 새 오류 보존율, 같은 사건 중복률, 세션당 건수·바이트, 유실 수, 원인 판별 가능 비율을 비교한다. 숫자 감축 목표는 baseline을 확보한 후 정한다. 원인 또는 최종 결과가 사라지면 축약부터 해제하고 저장 경로 문제는 기능 플래그로 롤백한다.
현재 실행된 것은 코드·문서 읽기 기반 조사와 이 계획 문서의 정적/화면 검토뿐이다. 위 수용 테스트와 PPI 운영 배포는 미실행이다. 무손실 요구·retention·서비스 인증 방식·SDK의 지침 적용 ACK 노출 여부는 구현 전 확정 항목이다.
7. 관련 문서와 후속 작업
- LiveKit agent 오류·프롬프트 상태와 템플릿 감사 로그 — 커밋 리뷰 (dcbbd4ab): 이 계획의 P0-1·P0-2 구현 결과와 전제 정정.
- 프롬프트 토큰 사전 검증 — 현재 구현과 운영 설계: 예방 정책은 이 문서와 연결하되 이번 로깅 개선의 완료 조건과 구분한다.
- 수업 중 게스트 미디어 진단 로깅 추가 가이드
- 활동·템플릿·스텝 동작 흐름
LLM용 복사 · 작업 맥락
목표: PPI web/socket/LiveKit 진단 로그를 S3에서 연결하고 불필요한 반복 로그를 축소한다. 기준 develop d235a6e0, 2026-09-08 조사. 사용자 보고 두 이슈는 토큰 초과 후 빈 프롬프트 세션과 활동 템플릿 삭제 후 회기 생성 실패다. 구현 전 계획이며 원인 확정·수용 테스트·앱 배포는 미완료다. 범위는 오류/프롬프트 상태, 삭제/생성 감사, 서버 S3 수집, 전환 ACK 최종 결과, 원인 보존 마스킹, 중복 축약이다. Daily Reports의 모든 경고를 실제 장애 또는 삭제 대상으로 단정하지 않는다. 설계 승인과 테스트 harness 확보 후 .worktrees/feat-s3-diagnostic-logging에서 구현한다.