py-runner APM 로깅 시스템 리서치
1. 태스크 요구사항 분석
1.1 목표
- py-runner 컨테이너 로그를 포지큐브 표준 입출력 형태로 변환
- APM(Application Performance Monitoring) 시스템과 통합하기 위한 로그 포맷 구현
1.2 요구사항 상세
- 로그는 JSON serialize 형태로 출력되어야 함
- 필수 포함 정보:
- API 요청(request) 정보: header, path, origin, x-forwarded-for, remoteAddress 등
- API 응답(response) 정보: HTTP 상태 코드, 지연 시간(latency), message
- 아테나 로깅 예시와 동일한 포맷으로 통일해야 함
2. 현황 분석
2.1 py-runner 현재 로깅 시스템
- 현재 py-runner는 기본 Python logging 모듈을 사용
- Agent, Sandbox, Dev 서버 각각 개별 로거 사용
- 로그 형식은 텍스트 기반이며 JSON 포맷이 아님
각 서버의 로그 설정:
# 예: apps/agent.py
logger = logging.getLogger("[AGENT]")
# uvicorn 로깅 설정
log_config = uvicorn.config.LOGGING_CONFIG
log_config["formatters"]["default"] = {"()": DefaultFormatter, "fmt": "%(levelprefix)s [AGENT]: %(message)s", "use_colors": True}
log_config["formatters"]["access"] = {"()": DefaultFormatter, "fmt": "%(levelprefix)s [AGENT]: %(message)s", "use_colors": True}
2.2 요구되는 로그 포맷 (아테나 로그 예시 분석)
아테나 로그 예시를 분석한 결과, 다음의 구조로 구성됨:
{
"level": "INFO",
"timestamp": "2025-03-06T02:23:14.883Z",
"pid": 7,
"hostname": "athena-deploy-57cf9ffcc8-lrg9q",
"req": {
"id": 230,
"method": "GET",
"url": "/chats/m1/logs/list?chat_threads_id=16390&sort=id%3ADESC&max_tokens=3000",
"query": { ... },
"params": { ... },
"headers": { ... },
"remoteAddress": "10.0.19.187",
"remotePort": 56328
},
"trace_id": "50d06b8a57aeccd5f44c2b4862420833",
"span_id": "ce80d5ec7359ee4b",
"trace_flags": "01",
"res": {
"statusCode": 200,
"headers": { ... }
},
"responseTime": 70,
"module": "athena",
"message": "request completed"
}
3. 로깅 구현 접근 방법 조사
3.1 FastAPI에서의 로깅 옵션
3.1.1 미들웨어 방식
- FastAPI의 미들웨어 기능을 사용하여 모든 요청/응답을 로깅
- 장점: 모든 엔드포인트에 일괄 적용 가능, 코드 분리 용이
- 단점: 요청 본문 등 일부 정보 접근에 추가 처리 필요
3.1.2 이벤트 핸들러 방식 ← soon deprecated
- FastAPI의 이벤트 핸들러(
@app.on_event
)를 활용 - 장점: 요청/응답 라이프사이클 이벤트에 따른 세밀한 제어 가능
- 단점: 구현이 복잡할 수 있음, 현재 deprecation 진행중임
3.1.3 로깅 라이브러리 통합 방식
python-json-logger
와 같은 라이브러리 활용- 장점: 기존 로깅 시스템 활용, 구현 간단
- 단점: HTTP 요청/응답 정보 수집을 위한 추가 작업 필요
3.2 로그 포맷팅 옵션
3.2.1 JSON 로그 포맷터
python-json-logger
라이브러리 사용 (이미 프로젝트에 포함됨)- 장점: JSON 형식으로 로그 출력 지원, 커스텀 포맷 구성 용이
- 단점: 추가 설정 작업 필요
3.2.2 커스텀 로그 포맷터
- Python의
logging.Formatter
확장 - 장점: 완전한 커스터마이징 가능
- 단점: 구현 복잡도 증가
4. 구현 방안 제안
4.1 미들웨어 기반 접근법
- 로깅 미들웨어 클래스 구현
- BaseHTTPMiddleware 확장
- 요청 시작 시간 기록 및 응답 완료 시간 계산
- 필요한 정보 수집 및 JSON 형식으로 로그 출력
- 로깅 설정 통합
- python-json-logger 사용하여 JSON 포맷 구성
- 세 서버 모두에 동일한 로깅 설정 적용
- 트레이싱 정보 추출 유틸리티
- 헤더에서 트레이싱 관련 정보 추출
- B3 포맷 및 W3C 트레이스컨텍스트 포맷 지원
4.2 로그 수집 항목
4.2.1 기본 메타데이터
- level: 로그 레벨
- timestamp: ISO 8601 형식의 타임스탬프
- pid: 프로세스 ID
- hostname: 호스트 이름
- module: 모듈 이름 ("py-runner")
4.2.2 요청 정보 (req)
- id: 요청 ID
- method: HTTP 메서드
- url: 전체 URL
- query: 쿼리 파라미터
- params: 경로 파라미터
- headers: 요청 헤더
- remoteAddress: 클라이언트 IP
- remotePort: 클라이언트 포트
4.2.3 응답 정보 (res)
- statusCode: HTTP 상태 코드
- headers: 응답 헤더
4.2.4 성능 및 추적 정보
- responseTime: 응답 시간 (ms)
- trace_id: 트레이스 ID
- span_id: 스팬 ID
- trace_flags: 트레이스 플래그
5. 고려 사항 및 주의점
5.1 성능 영향
- 로깅이 애플리케이션 성능에 미치는 영향 고려
- 로그 수준 조정으로 프로덕션 환경에서의 최적화 가능성
5.2 보안 고려사항
- 로그에 민감한 정보 포함 여부 검토
- 헤더 및 쿼리 파라미터에서 민감 정보 필터링 필요성
5.3 로그 크기 및 저장
- JSON 로그는 텍스트 로그보다 크기가 큼
- 로그 순환 및 압축 전략 필요
5.4 기존 로깅과의 통합
- 기존 py-runner 로깅 시스템과의 공존 방법
- 개발 및 디버깅을 위한 텍스트 로그 유지 필요성
6. 참고 자료
6.1 관련 라이브러리
- python-json-logger: https://github.com/madzak/python-json-logger
- OpenTelemetry Python: https://opentelemetry.io/docs/instrumentation/python/
- FastAPI 미들웨어 문서: https://fastapi.tiangolo.com/tutorial/middleware/
6.2 APM 관련 문서
- Distributed Tracing 표준: https://www.w3.org/TR/trace-context/
- B3 규격: https://github.com/openzipkin/b3-propagation
Member discussion