My LLM API Calls Were Failing Silently. Here's the Logging Setup I Wish I Had Earlier

개요

LLM API 호출 실패를 사일런트(silent)하게 감지하기 위한 로깅 설정의 중요성을 설명하며, 기존 API 로깅 방식의 한계를 지적하고 LLM 특화 로깅 데이터 구조 및 Node.js 기반의 로깅 래퍼(wrapper) 구현 예시를 제시합니다.

주요 내용

- LLM API의 잠재적 문제점: 일반적인 REST API와 달리 LLM API는 오류 응답 없이도 속도 저하, 예상보다 적은 토큰 사용, 반복 시도(retry)로 인한 지연 시간 증가, 스트리밍 실패 등 다양한 형태로 문제가 발생할 수 있으므로, 단순한 상태 코드(status code) 로깅만으로는 이러한 문제를 파악하기 어렵습니다.
- LLM 로깅에 필요한 핵심 데이터: LLM API 호출 건마다 요청 ID, 제공자(provider), 사용된 모델, 작업(operation), 상태, 지연 시간(latency_ms), 입력/출력 토큰 수, 예상 비용, 재시도 횟수, 대체(fallback) 여부, 스트리밍 여부, 오류 유형 및 메시지 등의 정보를 기록해야 합니다.
- Node.js 기반 로깅 래퍼 구현: OpenAI SDK를 활용하여 createLoggedChatCompletion 함수를 구현했으며, 이 함수는 LLM API 호출 전후의 시간, 입력 메시지의 해시, 재시도 및 대체 여부, 토큰 사용량 등을 로깅하고 오류 발생 시 error_type을 분류하여 기록합니다.
- 프롬프트 로깅의 주의점: 프로덕션 환경에서는 개인 정보, 기밀 데이터 유출 위험을 방지하기 위해 원시 프롬프트(raw prompt) 대신 프롬프트의 해시와 함께 메시지 수, 시스템 프롬프트 포함 여부, 입력 문자 수 등의 메타데이터를 로깅하는 것이 권장됩니다.
- Provider 로그의 한계: LLM 제공자(Provider)의 사용량 로그는 API 계층에서의 세부 정보를 제공하지만, 애플리케이션의 특정 기능, 사용자 인터랙션, 재시도 체인 등 애플리케이션 컨텍스트를 알지 못하므로 자체적인 애플리케이션 로깅이 여전히 중요합니다.
- 핵심적으로 유용한 로깅 필드: 모델(model), 제공자(provider), 지연 시간(latency_ms)의 분포(p50, p95, p99), 재시도 횟수(retry_count), 대체 발생 정보(fallback_from, fallback_to), 입력/출력 토큰 수(input_tokens, output_tokens), 정상화된 오류 유형(error_type) 등이 문제 해결에 가장 큰 도움이 됩니다.
- 주요 사일런트 실패 모니터링 대상:
1. 재시도 폭풍(Retry storms): 간헐적인 오류 응답으로 인해 재시도가 반복되어 지연 시간과 비용이 증가하는 현상
2. 대체(Fallback)가 주 경로가 되는 현상: 원래의 문제점을 숨기거나, 모델 부적합, 잘못된 타임아웃 설정 등으로 인해 대체 로직이 일반적인 경로가 되는 현상
3. 토큰 증가(Token creep): 시간이 지남에 따라 프롬프트가 점진적으로 길어져 비용이 상승하는 현상
4. 스트리밍 중단(Streaming interruptions): 스트리밍 응답이 중간에 끊기는 현상
5. 모델 불일치(Model mismatch): 설정 변경, 환경 변수 오류 등으로 인해 의도한 모델과 실제 사용되는 모델이 달라지는 현상
- 향상된 로깅 이벤트 구조: 타임스탬프, 사용자 ID 해시, 환경, 기능, 제공자, 모델, 작업, 스트리밍 여부, 상태, 지연 시간, 재시도 횟수, 대체 정보, 토큰 수, 예상 비용, 프롬프트 해시, 오류 유형 등을 포함하는 구조화된 로그 이벤트 예시를 제시합니다.

시사점

LLM API 호출 실패를 사전에 감지하고 근본 원인을 파악하기 위해서는 단순한 오류 로깅을 넘어, LLM의 특성을 반영한 상세한 컨텍스트 정보가 포함된 로깅 시스템 구축이 필수적이며, 이는 서비스 안정성과 비용 최적화에 직접적인 영향을 미칩니다.

원문 읽기 →
원문을 불러오는 중...

댓글

GitHub Discussions