1.3 Metric 모델과 Cardinality
Prometheus의 데이터 단위는 metric 이름과 label 집합으로 식별되는 time series입니다. 같은 metric이라도 label 조합이 달라지면 별도 series가 됩니다.
pg_stat_database_xact_commit{instance="db-a:9187",datname="orders"} 184203
pg_stat_database_xact_commit{instance="db-a:9187",datname="users"} 92117
위 두 줄은 이름이 같지만 datname이 달라 서로 다른 series입니다.
Metric type
Counter
Counter는 process가 재시작될 때를 제외하면 누적 증가합니다. transaction 수, 읽은 block 수, deadlock 누계가 대표적입니다. 현재값을 그대로 비교하지 않고 시간당 증가율을 계산합니다.
rate(pg_stat_database_xact_commit{datname!~"template.*"}[5m])
rate()는 reset을 고려하므로 두 시점의 값을 직접 빼는 것보다 안전합니다.
Gauge
Gauge는 오르내리는 현재 상태입니다. connection 수, database 크기, replica lag에 사용합니다. Gauge에 rate()를 적용하면 문법상 실행되더라도 의미 없는 결과가 나올 수 있습니다.
pg_stat_database_numbackends{datname="orders"}
Histogram
Histogram은 관측값을 bucket에 누적해 분포를 보존합니다. API latency처럼 p95/p99가 필요한 곳에 적합합니다. PostgreSQL Exporter의 통계 view 대부분은 gauge나 counter로 변환되므로, end-to-end query latency 분포는 애플리케이션 계측이나 별도 proxy에서 얻는 편이 낫습니다.
Series 수 계산
한 metric에 instance 20개, database 30개, user 50개, queryid 5,000개가 붙으면 이론상 조합은 다음과 같습니다.
20 × 30 × 50 × 5,000 = 150,000,000 series
실제 조합이 모두 생기지 않더라도 queryid, SQL 원문, user처럼 값의 종류가 많은 label은 빠르게 비용을 키웁니다. Prometheus는 각 고유 label 조합을 별도로 저장하고 색인합니다.
PostgreSQL에서 위험한 label
다음 값은 metric label보다 log나 trace에 두는 것이 안전합니다.
- SQL 원문
- session ID와 process ID
- transaction ID
- client IP 전체
- table 이름을 무제한으로 수집한 값
- tenant/user/request ID
pg_stat_statements를 metric으로 내보낼 때 queryid도 cardinality를 만듭니다. collector의 statement 수 제한을 사용하고 SQL 원문 포함은 기본적으로 끕니다.
좋은 label 설계
운영 중 실제로 집계하거나 필터링할 차원만 남깁니다.
environment="prod"
cluster="orders-primary"
instance="db-a:9187"
datname="orders"
role="primary"
prod_orders_primary_db_a처럼 모든 차원을 metric 이름에 합치지 않습니다. 이름은 측정 대상을 표현하고, 배포 환경과 instance는 label로 구분합니다.
Prometheus 공식 naming guide에 따라 시간은 seconds, 크기는 bytes, 비율은 0부터 1 사이 값으로 통일하면 서로 다른 dashboard와 rule을 조합하기 쉽습니다.
Cardinality를 점검하는 질문
새 collector나 label을 추가하기 전에 확인합니다.
- label 값의 종류는 현재 몇 개이며 계속 증가하는가?
- instance/database/table 수를 곱하면 series가 몇 개 생기는가?
- 이 차원으로 alert하거나 집계할 일이 실제로 있는가?
- 같은 질문을 log query로 늦게 조회해도 되는가?
- scrape 시간과
scrape_samples_post_metric_relabeling이 얼마나 증가했는가?
참고: Prometheus Metric and label naming, Prometheus Instrumentation