본문으로 건너뛰기

OpenMetrics 탐색기

OpenMetrics 탐색기는 WhaTap에서 제공하는 메트릭 데이터 조회 및 시각화 도구입니다. 수집된 메트릭을 PromQL로 조회하고, 결과를 차트(Graph)와 테이블(Table)로 시각화합니다.

주요 기능

  • PromQL 쿼리를 통한 메트릭 조회
  • Graph/Table 뷰로 데이터 시각화
  • 시간 범위 선택 시 자동으로 promql에 시간 입력
  • 실시간 메트릭 모니터링

화면 구성

  • 상단: 시간 범위 선택기, 쿼리 입력창
  • 중앙: Graph/Table/Stacked Bar 뷰 전환 버튼
  • 하단: 조회 결과 표시 (그래프 또는 테이블)

왜 PromQL이 필요한가요?

OpenMetrics는 Prometheus 메트릭 포맷을 기반으로 다양한 시스템과 애플리케이션의 시계열 지표를 수집합니다. Prometheus는 오픈소스 모니터링 도구로, CPU 사용률, 메모리 사용량, HTTP 요청 수, 에러율 등과 같은 수치 기반의 시간 흐름 데이터를 메트릭 지표로 저장합니다.

이러한 지표들은 대부분 수초 단위로 지속적으로 수집되며, 시간에 따라 끊임없이 변화하는 '시계열 데이터(time-series data)'의 형태를 가집니다.

하지만 단순히 데이터를 수집하는 것만으로 "지금 서비스가 정상인가?", "에러 비율이 평소보다 높아졌는가?", "어떤 API가 느려졌는가?" 같은 의미 있는 분석이 어렵습니다.

그래서 OpenMetrics 탐색기에서 수집된 메트릭을 분석할 수 있는 쿼리 언어가 필요하고, 그 역할을 하는 것이 바로 PromQL(Prometheus Query Language)입니다.

PromQL을 사용하면 다음과 같은 분석이 가능합니다.

  • 실시간 모니터링: 현재 시스템 상태를 즉시 확인 (현재 CPU 사용률, 활성 사용자 수 등)
  • 추세 분석: 시간에 따른 변화 패턴 파악 (최근 1시간 동안 초당 요청 수 증가율)
  • 비교 분석: 여러 서버나 서비스 간의 지표 비교 (서버별 에러율, 지역별 응답 시간)
  • 집계 및 계산: 복잡한 수학 연산과 통계 계산 (전체 에러율, 평균 응답 시간, 상위 10개 느린 API)
  • 알림 조건 설정: 특정 임계값 초과 시 자동 알림 (에러율 5% 이상, 메모리 사용률 90% 이상)

PromQL 사용자 가이드

쿼리 실행 방식

쿼리설명
Instant Query (즉시 쿼리)특정 시점의 데이터를 조회함. Table 탭에서 사용됨
Range Query (범위 쿼리)시작 시간과 종료 시간 사이의 데이터를 일정한 간격으로 조회함

데이터 타입

PromQL 표현식은 4가지 타입으로 평가됩니다.

타입설명
Instant Vector각 시계열에서 단일 샘플을 포함하는 시계열 집합 (모두 동일한 타임스탬프)
Range Vector각 시계열에서 시간 범위의 데이터 포인트를 포함하는 시계열 집합
Scalar단순한 숫자 값
String단순한 문자열 값

기본 사용법

1. 메트릭 선택(Instant Vector Selectors)

기본 메트릭 조회

nginx_http_response_count_total

레이블 필터링

nginx_http_response_count_total{status="200"}

여러 레이블 조건

nginx_http_response_count_total{method="GET", status="200"}

2. 레이블 매칭 연산자

연산자설명
=레이블 값이 정확히 일치
!=레이블 값이 일치하지 않음
=~레이블 값이 정규표현식과 일치
!~레이블 값이 정규표현식과 일치하지 않음

정규표현식 예제

# staging, testing, development 환경만 조회
nginx_http_response_count_total{environment=~"staging|testing|development"}

# GET 메소드를 제외한 모든 메소드
nginx_http_response_count_total{method!="GET"}

# rep로 시작하는 replica 조회
nginx_http_response_count_total{replica=~"rep.*"}

3. 시간 범위 선택(Range Vector Selectors)

현재 시점부터 과거 특정 기간의 데이터를 선택합니다.

# 최근 5분간의 데이터
nginx_http_response_count_total[5m]

# 최근 1시간의 데이터
nginx_http_response_count_total{status="200"}[1h]

4. 시간 오프셋(Offset Modifier)

과거 특정 시점의 데이터를 조회합니다.

# 5분 전의 값
nginx_http_response_count_total offset 5m

# 1주일 전의 5분간 비율
rate(nginx_http_response_count_total[5m] offset 1w)

# 미래 비교 (음수 offset)
rate(nginx_http_response_count_total[5m] offset -1w)

실용 예제

예제 1: 상태 코드별 요청 수 조회

nginx_http_response_count_total{instance="http://192.168.100.122:4040/metrics"}

예제 2: 특정 상태 코드만 조회

# 200 응답만
nginx_http_response_count_total{status="200"}

# 4xx 에러만(정규표현식)
nginx_http_response_count_total{status=~"4.."}

# 5xx 에러만
nginx_http_response_count_total{status=~"5.."}

예제 3. 메소드와 상태 코드 조합

# GET 요청 중 200 응답
nginx_http_response_count_total{method="GET", status="200"}

# POST, PUT, DELETE 요청 중 404 응답
nginx_http_response_count_total{method=~"POST|PUT|DELETE", status="404"}

예제 4. 메트릭 이름으로 검색

# "job:"로 시작하는 모든 메트릭
{__name__=~"job:.*"}

# nginx로 시작하는 모든 메트릭
{__name__=~"nginx.*"}

예제 5. 최근 시간 범위 데이터

# 최근 5분간의 nginx 응답
nginx_http_response_count_total{status="200"}[5m]

# 최근 1시간의 404 에러
nginx_http_response_count_total{status="404"}[1h]

예제 6. 시간대 비교

# 현재 값과 1시간 전 값 비교
nginx_http_response_count_total{status="200"}
nginx_http_response_count_total{status="200"} offset 1h

# 어제 같은 시간의 데이터
nginx_http_response_count_total offset 1d

집계 함수

집계 함수(Aggregation Functions)는 여러 시계열 데이터를 하나로 결합하여 계산합니다.

sum()

모든 시계열의 값을 더합니다.

# 모든 인스턴스의 요청 수 합계
sum(nginx_http_response_count_total)

# 상태 코드별로 그룹화하여 합계
sum by (status) (nginx_http_response_count_total)

# 인스턴스별로 그룹화하여 합계
sum by (instance) (nginx_http_response_count_total)

avg()

모든 시계열의 평균값을 계산합니다.

# 모든 인스턴스의 평균 응답 수
avg(nginx_http_response_count_total)

# 상태 코드별 평균
avg by (status) (nginx_http_response_count_total)

count()

시계열의 개수를 셉니다.

# 전체 시계열 개수
count(nginx_http_response_count_total)

# 상태 코드별 시계열 개수
count by (status) (nginx_http_response_count_total)

max() / min()

시계열의 최대값과 최소값을 계산합니다.

# 최대값
max(nginx_http_response_count_total)

# 최소값
min(nginx_http_response_count_total)

# 상태 코드별 최대값
max by (status) (nginx_http_response_count_total)

topk() / bottomk()

지정한 수(K)만큼 상위 또는 하위 시계열을 반환합니다.

# 상위 5개 시계열
topk(5, nginx_http_response_count_total)

# 하위 3개 시계열
bottomk(3, nginx_http_response_count_total)

# 상태 코드별 상위 3개
topk(3, sum by (status) (nginx_http_response_count_total))

시계열 함수

rate()

가장 많이 사용되는 함수로, Counter 메트릭의 초당 평균 증가율을 계산합니다.

# 최근 5분간 초당 평균 요청 수
rate(nginx_http_response_count_total[5m])

# 상태 코드 200의 초당 평균 요청 수
rate(nginx_http_response_count_total{status="200"}[5m])

# 모든 인스턴스의 초당 총 요청 수
sum(rate(nginx_http_response_count_total[5m]))
주의

주의사항

  • Counter 메트릭에만 사용
  • 시간 범위는 스크랩 간격의 최소 2배 이상 권장 (예: 스크랩 간격 30초 → [1m] 이상)
  • 카운터 리셋(서버 재시작 등)을 자동으로 처리

increase()

지정한 시간 범위 동안의 총 증가량을 계산합니다.

# 최근 5분간 총 요청 수
increase(nginx_http_response_count_total[5m])

# 최근 1시간 동안의 에러 수
increase(nginx_http_response_count_total{status=~"5.."}[1h])

rate()와 increase()의 관계

increase(v[5m]) = rate(v[5m]) × 300초

  • rate(): 초당 비율
  • increase(): 절대 증가량

irate()

마지막 두 데이터 포인트를 기반으로 초당 순간 증가율을 계산합니다.

# 즉시 증가율
irate(nginx_http_response_count_total[5m])

irate() vs rate()

  • irate(): 빠르게 변하는 카운터에 적합, 짧은 스파이크 감지
  • rate(): 알림 및 느리게 변하는 카운터에 적합, 평균값 제공

시간 범위 함수

특정 시간 범위 내에서 값을 집계합니다.

avg_over_time()

시간 범위 평균 함수입니다.

# 최근 10분간 평균값
avg_over_time(nginx_http_response_count_total[10m])

max_over_time() / min_over_time()

지정한 시간의 최대/최소값을 계산하는 시간 범위 함수입니다.

# 최근 1시간 동안 최대값
max_over_time(nginx_http_response_count_total[1h])

# 최근 1시간 동안 최소값
min_over_time(nginx_http_response_count_total[1h])

sum_over_time()

지정한 기간의 값을 더한 시간 범위 합계 함수입니다.

# 최근 5분간 모든 값의 합
sum_over_time(nginx_http_response_count_total[5m])

중요 규칙: Rate then Sum

이 규칙은 Counter 메트릭에 rate(), increase(), irate() 같은 시계열 함수를 사용할 때 모든 집계 함수(sum, avg, max, min, count 등)에 적용됩니다.

주의

항상 rate() 먼저, 그 다음 sum()

Counter 메트릭을 집계할 때 반드시 이 순서를 지켜야 합니다.

🔵 올바른 방법

# rate()를 먼저 적용한 후 sum()
sum(rate(nginx_http_response_count_total[5m]))

잘못된 방법

# sum()을 먼저 하면 카운터 리셋 시 문제 발생
rate(sum(nginx_http_response_count_total[5m]))

Counter 메트릭을 sum()으로 먼저 합치면, 개별 서버의 카운터 리셋(재시작)을 감지할 수 없게 됩니다. 서버 한 대가 재시작되면 전체 합계가 갑자기 감소하고, rate()는 이를 음수 증가율이나 비정상적인 스파이크로 잘못 계산합니다. 반면 rate()를 먼저 적용하면 각 서버별로 카운터 리셋을 정확히 감지하고 처리할 수 있습니다.

실전 예제

예제 1. 초당 요청 수 (RPS) 계산

# 전체 RPS
sum(rate(nginx_http_response_count_total[5m]))

# 상태 코드별 RPS
sum by (status) (rate(nginx_http_response_count_total[5m]))

# 메소드별 RPS
sum by (method) (rate(nginx_http_response_count_total[5m]))
정보

전체 Requests Per Second(RPS) PromQL에 대한 설명

sum(rate(nginx_http_response_count_total[5m]))이 왜 RPS일까?

  1. nginx_http_response_count_total은??

    • Counter 메트릭: 서버 시작 이후 누적 응답 수
    • 예: 1000 → 1050 → 1120 → 1180 → 1250...
  2. rate(...[5m])은 무엇일까?

    • 최근 5분간 데이터를 보고 초당 평균 증가율 계산
    • 예시: 5분 전: 1000 현재: 1300 차이: 300개 (5분 = 300초) rate = 300 / 300초 = 1.0 requests/second

    → rate()의 결과 = 초당 요청 수 (RPS)

  3. sum()은 왜 필요한가?

    • 여러 서버/레이블의 rate 값을 모두 더함
    • 예: server1, status=200 → 10 req/s server1, status=404 → 2 req/s server2, status=200 → 15 req/s server2, status=404 → 3 req/s 합계 = 30 req/s

결론: sum(rate(nginx_http_response_count_total[5m])) = 모든 서버의 초당 총 요청 수 (RPS)


참고. 5분간 총 요청 수를 원하면 increase() 사용 sum(increase(nginx_http_response_count_total[5m])) = 5분간 총 요청 수

예제 2. 에러율 계산

# 전체 요청 대비 5xx 에러 비율 (%)
sum(rate(nginx_http_response_count_total{status=~"5.."}[5m])) / sum(rate(nginx_http_response_count_total[5m])) * 100

# 전체 요청 대비 4xx 에러 비율
sum(rate(nginx_http_response_count_total{status=~"4.."}[5m])) / sum(rate(nginx_http_response_count_total[5m]))

예제 3. 상위 N개 인스턴스 찾기

# 요청이 가장 많은 상위 5개 인스턴스
topk(5, sum by (instance) (rate(nginx_http_response_count_total[5m])))

# 에러가 가장 많은 상위 3개 인스턴스
topk(3, sum by (instance) (rate(nginx_http_response_count_total{status=~"5.."}[5m])))

예제 4. 시간대별 비교

# 현재 RPS
sum(rate(nginx_http_response_count_total[5m]))

# 1시간 전 RPS
sum(rate(nginx_http_response_count_total[5m] offset 1h))

# 어제 같은 시간 RPS
sum(rate(nginx_http_response_count_total[5m] offset 1d))

예제 5. 평균 응답 수

# 인스턴스별 평균 응답 수
avg by (instance) (rate(nginx_http_response_count_total[5m]))

# 상태 코드별 평균
avg by (status) (rate(nginx_http_response_count_total[5m]))

수학 연산자

산술 연산

# 더하기
sum(rate(nginx_http_response_count_total{status="200"}[5m]))
+
sum(rate(nginx_http_response_count_total{status="201"}[5m]))

# 빼기
sum(rate(nginx_http_response_count_total[5m])) - sum(rate(nginx_http_response_count_total{status=~"5.."}[5m]))

# 곱하기 (바이트를 MB로 변환)
nginx_http_response_size_bytes / 1024 / 1024

# 나누기 (비율 계산)
sum(rate(nginx_http_response_count_total{status=~"5.."}[5m])) / sum(rate(nginx_http_response_count_total[5m]))

비교 연산

# 100보다 큰 값만
nginx_http_response_count_total > 100

# 특정 값과 같은 경우
nginx_http_response_count_total == 200

# 범위 지정
nginx_http_response_count_total > 100 and nginx_http_response_count_total < 1000

실전 팁

1. 스크랩(수집 주기)별 시간 범위 선택

스크랩 간격최소 시간 범위권장 시간 범위이유
15초[30s][1m] 이상2~4개 데이터 포인트 확보
30초[1m][2m] 이상2~4개 데이터 포인트 확보
1분[2m][5m] 이상2~4개 데이터 포인트 확보

2. 그룹화 레이블 선택

# 너무 세분화 (너무 많은 시계열)
sum by (instance, method, status, path) (rate(nginx_http_response_count_total[5m]))

# 적절한 그룹화
sum by (status) (rate(nginx_http_response_count_total[5m]))

3. 알림 규칙 작성 시

# 5분간 에러율이 5% 이상인 경우
sum(rate(nginx_http_response_count_total{status=~"5.."}[5m])) / sum(rate(nginx_http_response_count_total[5m]))
> 0.05

4. 함수 조합 순서

# 1. rate() 먼저
# 2. 집계 함수 (sum, avg 등)
# 3. 수학 연산

# 올바른 순서
sum(rate(nginx_http_response_count_total[5m])) * 100

기타 함수

abs()

값의 절대값을 반환하는 함수입니다.

abs(rate(nginx_http_response_count_total[5m]) - 100)

round()

값을 가장 가까운 정수 또는 지정한 단위로 반올림합니다.

# 소수점 반올림
round(sum(rate(nginx_http_response_count_total[5m])))

# 10 단위로 반올림
round(sum(rate(nginx_http_response_count_total[5m])), 10)

clamp_max() / clamp_min()

값이 지정한 최대값이나 최소값을 넘지 않도록 제한합니다.

# 최대값 1000으로 제한
clamp_max(nginx_http_response_count_total, 1000)

# 최소값 0으로 제한
clamp_min(nginx_http_response_count_total, 0)

주의사항

빈 레이블 값 매칭

빈 레이블 값을 매칭하면 해당 레이블이 설정되지 않은 모든 시계열도 선택됩니다.

# environment 레이블이 없거나 빈 값인 모든 시계열
nginx_http_response_count_total{environment=""}

필수 선택자

벡터 선택자는 반드시 메트릭 이름이나 빈 문자열과 일치하지 않는 레이블 매처를 하나 이상 지정해야 합니다.

# ❌ 잘못된 예
{job=~".*"}

# ✅ 올바른 예
{job=~".+"}
{job=~".*", method="get"}

성능 고려사항

효율적인 쿼리를 위한 팁

메트릭 이름만 사용하면 수천 개의 시계열이 선택될 수 있습니다.

  • 항상 적절한 레이블 필터를 사용하여 결과를 제한하세요.
  • 처음에는 Table 뷰에서 결과를 확인하고, 적절한 수준으로 필터링한 후 차트 뷰로 전환하세요.
  • 수백 개 이하의 시계열이 이상적입니다.

Staleness (오래된 데이터)

시계열이 더 이상 수집되지 않으면 "stale"로 표시됩니다.

  • Stale로 표시된 후에는 쿼리 결과에 포함되지 않습니다.
  • 기본적으로 5분 동안 데이터가 수집되지 않으면 stale로 간주됩니다.

정규표현식

Prometheus는 RE2 문법을 사용합니다.

  • 모든 정규표현식은 완전히 앵커링됩니다. (자동으로 ^$가 추가됨)
  • env=~"foo"env=~"^foo$"와 동일합니다.

주석

# 이것은 주석입니다
nginx_http_response_count_total{status="200"} # 라인 끝 주석도 가능

추천 학습 순서

  • 기초: rate(), sum(), avg()
  • 중급: increase(), irate(), topk()
  • 고급: 복잡한 비율 계산, 여러 함수 조합