본문으로 건너뛰기

11.1 로그

Patroni는 데몬으로 상시 동작하므로, 장애가 지나간 뒤 무슨 일이 있었는지 재구성할 1차 자료는 로그입니다. 어느 시점에 leader lock을 잃었는지, 왜 demote를 결정했는지는 DCS에도 메트릭에도 남지 않고 로그에만 남습니다. 로그 동작은 patroni.yml의 log 섹션에서 제어합니다.

출력 형식과 레벨​

log.type은 plain(기본)과 json 중 하나입니다. json을 쓰려면 python-json-logger 패키지가 필요합니다. plain 형식의 기본 포맷은 "%(asctime)s %(levelname)s: %(message)s"이고 log.format으로 바꿉니다. json 형식에서는 format에 문자열 대신 리스트를 주어 어떤 필드를 내보낼지 정의하고, key-value 표기로 필드 이름을 바꿔 붙일 수도 있습니다.

레벨은 둘로 나뉩니다. log.level(기본 INFO)이 일반 로그 레벨이고, 예외 스택 트레이스를 어느 레벨로 기록할지는 log.traceback_level(기본 ERROR)이 따로 정합니다. timestamp 형식은 log.dateformat으로 조정합니다.

json 전용 옵션인 log.static_fields는 모든 레코드에 고정 필드를 추가합니다. 여러 노드의 로그를 중앙 수집기로 모을 때 노드 식별자를 넣어 두면 출처 구분이 쉬워집니다.

log:
type: json
level: INFO
traceback_level: ERROR
static_fields:
node: patroni-node1
loggers:
patroni.postmaster: WARNING

log.loggers는 모듈별 레벨 오버라이드입니다. 전체 레벨은 그대로 두고 유난히 소란한 모듈만 WARNING으로 낮추거나, 추적 중인 모듈만 DEBUG로 올리는 식으로 씁니다.

파일 로깅과 로테이션​

log.dir을 지정하면 stderr 대신 파일로 기록합니다. 디렉토리는 미리 존재해야 하고 Patroni를 실행하는 사용자가 쓸 수 있어야 합니다. 파일 로깅의 기본 로테이션은 25MB 파일 4개입니다. 파일 크기는 log.file_size, 보관 개수는 log.file_num으로 조정합니다. log.mode는 로그 파일 권한(예: 0644)이고, 지정하지 않으면 umask를 따릅니다.

log:
dir: /var/log/patroni
file_num: 8
mode: 0644
노트

기본 보관량 100MB(25MB x 4)는 로그가 조용한 클러스터에서는 며칠 분량이지만, DEBUG 레벨을 켜거나 장애로 오류가 쏟아지는 상황에서는 빠르게 밀려납니다. 장애 분석에 필요한 구간이 로테이션으로 사라지기 전에 수집기로 옮기거나 file_num을 여유 있게 설정해 두는 편이 안전합니다.

비동기 로깅 큐​

Patroni의 로깅은 2단계입니다. 로그 레코드를 먼저 메모리 큐에 넣고, 별도의 로깅 스레드가 큐에서 꺼내 stderr 또는 파일에 씁니다. 로그 저장소의 I/O가 느려져도 HA 루프를 도는 스레드가 쓰기에 직접 막히지 않도록 한 구조입니다.

큐 크기는 log.max_queue_size로 정하며 기본 1000 레코드입니다. 기본 설정 기준으로 약 1시간 20분 분량의 로그에 해당합니다.

heartbeat 로그와 deduplicate_heartbeat_logs​

Patroni는 매 HA 루프마다 자신의 판단을 로그로 남깁니다. 안정 상태에서는 매 loop_wait(기본 10초)마다 "leader lock을 유지했고 할 일이 없다"는 취지의 같은 내용이 반복되므로, 로그 대부분이 이 heartbeat로 채워집니다. log.deduplicate_heartbeat_logs(기본 false)를 true로 켜면 내용이 같은 heartbeat 로그의 반복을 억제합니다.

경고

heartbeat 로그의 반복은 노이즈이기만 한 것이 아닙니다. 각 레코드의 timestamp 간격이 곧 HA 루프가 제때 돌았다는 증거라서, 루프가 I/O 대기 등으로 정체된 구간을 로그 간격이 벌어진 지점으로 찾아내는 진단이 가능합니다. deduplicate_heartbeat_logs를 켜면 저장 공간을 아끼는 대신 이 타이밍 정보를 잃습니다.

장애 분석에서 보는 로그 패턴​

로그 메시지의 정확한 문구는 버전에 따라 달라지므로, 특정 문자열을 외우기보다 패턴 단위로 보는 접근이 오래 갑니다. 장애 시각 전후로 보통 다음 순서로 검사합니다.

  • heartbeat 간격이 loop_wait를 크게 벗어난 구간이 있는지. 있다면 그 시각에 Patroni 프로세스나 호스트 자체가 정체된 것입니다.
  • promote 또는 demote 결정이 기록된 지점과 그 직전의 판단 근거. role 전환 로그는 failover 재구성의 축이 됩니다.
  • DCS 통신 오류와 재시도 기록. leader lock 갱신 실패로 이어졌다면 시나리오 A의 전개를 따라갑니다.

json 로깅을 쓰면 이 검사를 수집기 쿼리로 대신할 수 있습니다.

정리​

  • 로그 동작은 log 섹션 하나로 제어합니다. type(plain/json), level과 traceback_level, format, json 전용 static_fields, 모듈별 loggers 오버라이드가 있습니다.
  • dir을 지정하면 파일 로깅으로 전환되고 기본 25MB x 4 로테이션이 적용됩니다. file_size, file_num, mode로 조정합니다.
  • 로깅은 메모리 큐(기본 1000 레코드)와 별도 스레드를 거치는 비동기 구조입니다.
  • heartbeat 로그의 timestamp 간격은 HA 루프 타이밍의 진단 자료입니다. deduplicate_heartbeat_logs는 이 정보와 저장 공간을 맞바꾸는 설정입니다.