본문으로 건너뛰기

1.2 네 가지 Signal

Metric, log, trace, profile은 같은 사건을 다른 해상도로 봅니다. 하나를 만능 도구처럼 쓰기보다 각 signal이 잘 답하는 질문을 구분해야 조사 시간이 짧아집니다.

Signal잘 답하는 질문PostgreSQL 예시
Metric언제부터, 얼마나 자주, 얼마나 큰가?connection 수, commit rate, replica lag
Log그 시점에 어떤 사건이 기록됐는가?deadlock, checkpoint, authentication failure
Trace요청이 어느 구간에서 시간을 썼는가?API → pool 대기 → SQL 실행
ProfileCPU/메모리를 어느 코드 경로가 소비했는가?애플리케이션 CPU hotspot, exporter overhead

Metric에서 시작한다

Metric은 시간 범위를 빠르게 줄이는 데 유리합니다. 예를 들어 API p95 latency가 14시 03분부터 상승했고, 같은 시각 pg_stat_database_xact_commit 증가율은 유지되지만 lock wait session이 늘었다면 query 처리량보다 동시성 문제를 먼저 의심할 수 있습니다.

Metric만으로는 어떤 SQL이 누구를 막았는지 알기 어렵습니다. 여기서 원본 view와 log로 내려갑니다.

SELECT pid,
wait_event_type,
wait_event,
pg_blocking_pids(pid) AS blocking_pids,
query
FROM pg_stat_activity
WHERE wait_event_type = 'Lock';

Log로 사건을 확인한다

PostgreSQL log는 deadlock, crash recovery, checkpoint 지연, connection 오류처럼 개별 사건을 남깁니다. 운영에서는 최소한 다음 필드가 구조적으로 구분되어야 합니다.

  • timestamp와 timezone
  • database/user/application name
  • process ID와 session ID
  • SQLSTATE
  • query ID 또는 statement 정보

Metric spike와 log를 연결하려면 시계가 맞아야 합니다. host, container, PostgreSQL, 애플리케이션의 timezone 표기가 달라도 timestamp를 UTC로 정규화하면 같은 사건을 찾기 쉽습니다.

Trace로 요청 경로를 분해한다

Trace는 사용자의 한 요청을 여러 span으로 나눕니다. HTTP handler가 800ms 걸렸고 database span은 40ms라면 PostgreSQL 튜닝을 시작할 이유가 약합니다. 반대로 pool acquire span이 600ms라면 SQL 실행보다 connection 부족이나 긴 transaction을 먼저 봅니다.

OpenTelemetry database semantic convention을 사용하면 db.system.name=postgresql, operation, server address 같은 공통 attribute로 서비스가 달라도 같은 방식으로 분석할 수 있습니다. SQL 원문은 개인정보와 cardinality 문제를 만들 수 있으므로 수집 범위를 통제합니다.

Profile은 마지막 확대경이다

Profile은 지속적으로 높은 CPU를 소비하는 함수, allocation이 몰리는 코드, I/O에서 대기하는 stack을 보여 줍니다. PostgreSQL 서버 자체의 깊은 분석에는 perf, eBPF, PostgreSQL wait event가 더 직접적인 경우가 많습니다. 애플리케이션이나 exporter 프로세스가 병목인지 확인할 때 profile이 특히 유용합니다.

Correlation key를 준비한다

서로 다른 signal을 같은 사건으로 묶으려면 공통 차원이 필요합니다.

  • service.name, service.instance.id
  • cluster, environment, region
  • PostgreSQL application_name, datname
  • trace ID와 span ID
  • 배포 version 또는 Git SHA

Prometheus label에 trace ID나 query 원문처럼 값이 계속 늘어나는 식별자를 넣어서는 안 됩니다. metric에는 낮은 cardinality 차원을 두고, 개별 ID는 log와 trace에 보관합니다.

조사 순서

  1. 서비스 metric으로 영향 시간과 범위를 정합니다.
  2. PostgreSQL/pool/node metric으로 병목 계층을 분류합니다.
  3. 원본 SQL view와 log로 사건을 확인합니다.
  4. trace로 사용자 요청 경로를 분해합니다.
  5. 코드 수준 병목이 남으면 profile을 사용합니다.

서비스 metric에서 profile까지 필요한 해상도로 내려가는 조사 순서

참고: OpenTelemetry Signals, Database client span semantic conventions