Codex 로깅 버그가 로컬 SSD에 TB 단위 쓰기를 발생시켜 SSD 수명을 빠르게 소모할 수 있음

1 day ago 3
  • Codex가 로컬 SQLite 피드백 로그 DB에 지속적으로 대량 데이터를 기록하며, 한 사용자 환경에서 21일 가동 후 메인 SSD에 약 37TB가 기록됨
  • 이를 환산하면 연간 약 640TB, 1TB SSD 기준 연 약 640회 전체 쓰기에 해당하며, 일부 컨슈머 SSD의 보증 수명(약 600 TBW)을 1년 이내에 소진할 수 있음
  • 보존 행은 약 50만 개에 불과하지만 AUTOINCREMENT 카운터는 55억 ID를 넘겨, 보존 행과 누적 삽입 ID 사이에 약 1만 배 격차가 존재
  • 원인은 SQLite 피드백 로그 싱크가 글로벌 TRACE 기본값(Targets::new().with_default(Level::TRACE))으로 설정되어, 의존성 내부 로그와 대용량 raw 프로토콜 페이로드까지 모두 영구 기록하기 때문
  • 2026년 6월 22일 두 개의 PR이 병합되어 약 85%의 로그를 차단함에 따라 이슈가 종료됨

핵심 증상 및 영향 범위

  • Codex가 다음 파일에 지속적으로 대량 기록 발생
    • ~/.codex/logs_2.sqlite
    • ~/.codex/logs_2.sqlite-wal
    • ~/.codex/logs_2.sqlite-shm
  • 21일 가동 후 메인 SSD에 약 37TB 기록, 프로세스/파일 단위 점검에서 Codex SQLite 로그가 주요 지속 기록원으로 확인됨
  • 연간 약 640TB로 환산, 1TB SSD 기준 연 약 640회 전체 드라이브 쓰기 수준
  • 일부 컨슈머 SSD는 약 600 TBW 등급으로, 보증 쓰기 수명을 1년 미만에 소진 가능

증거 데이터

  • Evidence1 — 쓰기 증폭(write amplification)

    • 현재 logs_2.sqlite 파일 크기: 1.2 GiB
    • 현재 보존 행: 506,149개
    • 누적 할당 row id: 5,543,677,486개
    • 보존 행(약 0.5M)과 누적 삽입 ID(55억+) 사이 약 1만 배 격차, WAL·인덱스·프루닝·체크포인트·페이지 재기록·기기 단위 증폭을 제외해도 10TB+ 규모의 과거 로그 churn 추정
  • Evidence2 — 레벨/타깃 분포

    • 보존 행 681,774개, 추정 보존 로그 콘텐츠 약 1,035.6 MiB
    • 레벨별 비중: TRACE 70.7%, INFO 25.7%, DEBUG 3.0%, WARN 0.6%
    • 최대 target+level 쌍
      • codex_api::endpoint::responses_websocket (TRACE) 527.4 MiB
      • codex_otel.log_only (INFO) 141.2 MiB
      • codex_otel.trace_safe (INFO) 121.2 MiB
      • log (TRACE) 97.4 MiB
    • 상위 소스는 글로벌 TRACE 로그, 미러링된 텔레메트리 로그, raw websocket/SSE 페이로드 기록이 대부분
    • codex_otel.log_only + codex_otel.trace_safe가 추가로 25.3% 차지, 해당 카테고리 필터링 시 표본 기준 보존 로그 바이트의 약 96% 제거 가능
    • 가장 빈번한 TRACE 소스(target=log)는 inotify event(예: ld.so.cache 128,764회), tokio-tungstenite 내부 호출, WouldBlock 등 저수준 항목이 다수
  • 쓰기 증폭 측정

    • 15초 표본에서 보존 행은 681,774개로 변동 없이, 약 36,211개 행이 삽입
    • 삽입→인덱싱→WAL 기록→프루닝이 반복되는 insert-and-prune 패턴으로 쓰기 증폭 발생

추정 원인

  • SQLite 피드백 로그 싱크가 글로벌 TRACE 기본값(Targets::new().with_default(Level::TRACE))으로 설치됨
  • 이로 인해 의존성/내부 로그와 대용량 raw 프로토콜 페이로드까지 모든 타깃이 TRACE 레벨로 영구 저장됨

제안된 수정 방향

  • 피드백 로그는 유지하되 기본 영구 저장 범위를 좁힐 것
    • SQLite 피드백 로그 싱크에 글로벌 TRACE 사용 금지
    • target=log, hyper_util, tokio-tungstenite 내부, inotify 스팸, 저수준 OpenTelemetry SDK 로그 등 저가치 노이즈의 임계값 상향 또는 제거
    • raw websocket/SSE 페이로드 전체 저장 대신 요약(이벤트 종류, 소요시간, 성공/실패, 토큰 사용량, 페이로드 바이트 길이) 저장
    • codex_otel.log_only / codex_otel.trace_safe 미러 이벤트는 디버깅에 유용한 경우 외 저장 회피
    • 스레드 단위 캡만으로는 부족하므로 글로벌 로그 DB 크기/쓰기 상한 추가
  • sqlite_logs_enabled = false 같은 옵션도 유용하나, 핵심 해결은 더 나은 기본 필터링

다중 플랫폼 재현 보고

  • macOS

    • macOS 15.7.7 / Codex 26.616.51431 환경에서 logs_2.sqlite 113M, MAX(id)=34,277,360에 보존 행 31,405개, 60초 표본 2회에서 약 초당 60회 쓰기 확인
    • 1~2시간 세션 동안 codex 프로세스가 약 50GB 기록한 사례 보고
  • Windows

    • Windows Codex Desktop(codex.exe app-server --analytics-default-enabled)에서 RUST_LOG=warn 및 명시적 trace 설정이 없는데도 TRACE 행이 지속 삽입됨
    • 보존 행 약 71k, sqlite_sequence의 logs 값은 1,850만 초과로 과거 insert/prune churn 다수
    • 10분 분포에서 TRACE 1,812행, 상위 TRACE 타깃에 codex_api::endpoint::responses_websocket(3.5MB+), codex_api::sse::responses 포함
    • 기대 동작: RUST_LOG=warn 시 의존성/내부 TRACE 및 대용량 페이로드를 지속 저장하지 않아야 함

추가 위험 및 임시 완화책

  • 데이터 손실 위험

    • 디스크가 가득 찬 상태에서 재부팅 시 Linux 로그인 실패 가능
    • Codex /goal 모드가 디스크 공간 확보를 시도하며 파일/폴더를 삭제해 데이터 손실 발생 가능
  • 임시 완화 스크립트

    • 실행 중 WAL을 트리밍하는 trim-codex-wal.sh(PRAGMA wal_checkpoint(TRUNCATE) 사용), cron으로 15분마다 실행 가능
    • 로그/WAL 파일 삭제 후 Codex 관련 프로세스에 SIGTERM→SIGKILL을 보내 디스크 공간을 즉시 확보하는 fix-codex-wal.sh
    • logs 테이블 삽입을 무시하는 SQLite 트리거(block_log_inserts)를 추가하면 WAL 증가가 멈춤, 되돌릴 때는 DROP TRIGGER IF EXISTS block_log_inserts
      • VACUUM은 DB를 재기록하므로 대용량 파일에서는 일회성 대형 쓰기를 유발할 수 있어, 트리거 추가 후 WAL 증가 중단 확인 뒤에 DELETE/VACUUM 실행 권장
      • 사설 SQLite 스키마 수정이므로 향후 Codex 업데이트/마이그레이션이 테이블 재생성, 트리거 제거 등으로 동작할 가능성 있음
    • 영구 수정 전까지 SSD 손상을 막으려면 해당 DB를 ramdisk에 두는 방법도 제시됨

해결 및 종료

  • 2026년 6월 22일 두 개의 PR 병합으로 약 85% 로그 절감, 이에 따라 이슈가 완료 처리됨
    • 모든 Responses WebSocket 이벤트 로깅 중단 (#29432)
    • 영구 로그에서 노이즈 타깃 필터링 (#29457)
  • 별도 제안 패치에서는 글로벌 TRACE 대신 INFO+ 기본 저장, codex_otel.log_only·codex_otel.trace_safe·hyper_util·log·opentelemetry_sdk 등을 WARN+로 상향
  • 수정 사항이 rust-v0.142.0으로 릴리스됨
Read Entire Article