본문으로 건너뛰기
버전: 5.1.0-11.2

R7. PromQL 연동 레퍼런스

Diátaxis: Reference · 대상: 운영자 / 관리자 (PromQL · Grafana 경험자) ← 목차로

이미 Grafana 대시보드나 PromQL에 익숙하다면, OPENMARU APM이 수집한 WAS · JVM · 시스템 · WEB · DBMS 메트릭을 표준 PromQL 호환 쿼리로 그대로 조회할 수 있습니다. 별도의 Prometheus 서버나 익스포터·스크레이프 설정 없이 APM 한 곳에서 수집·저장·질의·시각화가 끝나고, 기존 Grafana 대시보드 자산도 재사용할 수 있습니다.

  • APM의 세밀한 메트릭을 그대로 — JVM·GC·스레드·DB 커넥션풀·트랜잭션 메트릭에 표준 PromQL로 접근
  • 풍부한 라벨 — instance_id, ip_addr, agent_type 같은 APM 컨텍스트로 정밀 필터·집계
  • 저장 방식에 맞춘 rate/increase — 변화량(delta)으로 저장된 지표는 구간 합계로, 이미 초당 값으로 저장된 지표는 구간 평균으로 계산
  • 상대 시간 표현 — now, now-1h 같은 직관적 표현 지원 (표준 Prometheus에는 없는 편의 기능)

어떤 메트릭이 어떤 의미인지는 R2. 차트 지표 레퍼런스와 E3. 지표의 의미를 보세요. 콘솔 안에서 차트를 모아 보려면 H3. 나의 대시보드로도 충분합니다 — PromQL은 외부 연동·자동화가 필요할 때의 도구입니다.

여는 법 — 브라우저에서 http://{apm-server}/monitoring/api/v1/metric-explorer (Metric Explorer UI). 로그인에는 API 접근 키를 사용합니다 — 좌측 메뉴 ▸ 설정 ▸ 사용자에서 사용자 수정 버튼을 눌러 키를 생성·복사하세요.


5분 만에 시작하기​

가장 단순한 쿼리 — 한 줄이면 모든 WAS 인스턴스의 JVM 힙 사용량(현재값)이 나옵니다.

jvm_heap_heapUsed

특정 인스턴스만, 또는 특정 IP 대역만(정규식) 보고 싶을 때:

jvm_heap_heapUsed{instance_id="apm-was-01"}
jvm_heap_heapUsed{ip_addr=~"192\\.168\\.80\\..*"}

시간 함수를 적용해 지난 1시간 최댓값, 5분 평균 GC 빈도를 구합니다:

max_over_time(jvm_heap_heapUsed[1h])
rate(gc_G1_Young_Generation_gcCount[5m])

참고 정확한 메트릭 이름은 Metric Explorer의 드롭다운에서 고르거나 GET /api/v1/label/__name__/values로 확인하세요 (약 250개). GC 지표 이름은 gc_<수집기>_gcCount · gc_<수집기>_gcTime 이고, 수집기 이름은 JVM 의 GC 설정에 따라 다릅니다 (예: gc_G1_Young_Generation_gcCount, gc_PS_Scavenge_gcCount). 이 문서의 예시는 G1 을 씁니다.


기간을 지정해 조회하기​

범위 조회(/api/v1/query_range)는 시작/종료 시각과 step(데이터 간격)을 받습니다. 네 가지 시간 형식을 지원합니다.

형식예시비고
상대 시간now, now-1h, now-30m, now-1d가장 편리 — 단위 s/m/h/d
Unix epoch (초)1704067200shell date +%s
Unix epoch + 소수1704067200.123밀리초 정밀도
RFC33392026-05-10T09:00:00+09:00타임존 포함 가능

자주 쓰는 호출 예시:

# 최근 1시간 — 가장 흔한 케이스 (step 자동 15s)
curl -G "http://{apm-server}/monitoring/api/v1/query_range" \
--data-urlencode "query=jvm_heap_heapUsed" \
--data-urlencode "start=now-1h" \
--data-urlencode "end=now"

# 최근 7일 주간 추세 (step 자동 5m)
curl -G "http://{apm-server}/monitoring/api/v1/query_range" \
--data-urlencode "query=max_over_time(cpu_usage_cpuUsage[1h])" \
--data-urlencode "start=now-7d" \
--data-urlencode "end=now"

# step 직접 지정 (15초 간격)
curl -G "http://{apm-server}/monitoring/api/v1/query_range" \
--data-urlencode "query=rate(gc_G1_Young_Generation_gcCount[5m])" \
--data-urlencode "start=now-30m" \
--data-urlencode "end=now" \
--data-urlencode "step=15s"

# 특정 날짜 범위 (KST)
curl -G "http://{apm-server}/monitoring/api/v1/query_range" \
--data-urlencode "query=jvm_heap_heapUsed{agent_type=\"WAS\"}" \
--data-urlencode "start=2026-05-10T09:00:00+09:00" \
--data-urlencode "end=2026-05-11T18:00:00+09:00"

step을 지정하지 않으면 조회 범위에 따라 자동 계산됩니다:

조회 범위자동 step데이터 포인트 수 (예)권장 용도
12시간 이하15s1시간 ≈ 240실시간 · 표준 대시보드
12시간 ~ 2일1m24시간 ≈ 1,440일별 비교
2일 ~ 8일5m7일 ≈ 2,016주간 추세
8일 ~ 21일10m격주 추세
21일 이상30m30일 ≈ 1,440월간 비교

참고 원본 데이터는 2초 주기로 저장됩니다. step을 작게 하면 더 촘촘하지만 서버 부하가 커집니다 — 큰 step으로 시작해 필요할 때 줄여 가세요.

기간 조회는 다음 규칙을 따릅니다.

  • 응답의 시각은 step 경계로 맞춥니다. start 가 09:00:30 이고 step 이 1m 이면 첫 점은 09:00:00 입니다. 저장소가 step 경계 단위로 값을 묶기 때문입니다.
  • end 가 start 보다 앞서면 bad_data 오류(HTTP 400)가 납니다.
  • (end − start) ÷ step 이 11,000 을 넘으면 bad_data 오류(HTTP 400)가 납니다. step 을 크게 지정하세요. step 을 생략하면 이 상한을 넘지 않도록 step 을 늘립니다(약 229일보다 긴 범위).

한 쿼리가 저장소에서 읽는 양에도 상한이 있습니다. 시점 조회에도 같은 상한을 적용합니다.

  • 선택자나 창 함수 하나가 읽는 행(시리즈 수 × 시리즈당 행 수)은 2,000,000개까지입니다. 시리즈당 행 수는 함수 없는 선택자는 step 개수, 창 함수는 작은 구간 수, 시점 조회는 1 입니다. 그래서 읽을 수 있는 시리즈 수는 2,000,000 ÷ 시리즈당 행 수입니다. 예를 들어 3일 범위를 step 30초로 조회하면 시리즈당 8,641행이고 시리즈는 231개까지입니다. 넘으면 bad_data 오류(HTTP 400) query selects too many series (more than <시리즈 상한> for this range and step); use a coarser step, a shorter range or a narrower selector 가 납니다. 저장소에 시리즈를 상한보다 하나 많은 수까지만 요청하므로, 넘는 시리즈 대부분을 읽기 전에 거절합니다. 이 요청 수는 저장 단위(measurement)마다 적용되므로, 지표 하나가 저장 단위 여러 개에 나뉘어 있으면 그 수만큼 더 읽을 수 있습니다. step 을 크게 하거나 조회 기간을 줄이거나 라벨로 시리즈를 좁히세요. 상한은 수집 서버 시스템 속성 promql.leaf.max.rows 로 바꿀 수 있습니다. 원 샘플을 읽는 계산(원 샘플 창 함수, 아래 "Prometheus와 다른 점" 에서 원 샘플로 계산하는 rate · irate · increase, timestamp())은 이 절의 상한 대신 원 샘플 상한(아래 "지원 함수" 참고)을 씁니다.
  • 한 쿼리의 선택자·창 함수가 읽는 행을 모두 합쳐 8,000,000개까지입니다. 넘으면 bad_data 오류(HTTP 400) query reads too many rows (<읽은 행 수> > <상한>); use a coarser step, a shorter range or a narrower selector 가 납니다. 상한은 수집 서버 시스템 속성 promql.query.max.rows 로 바꿀 수 있습니다.
  • 시리즈당 행 수가 5,000 을 넘는 선택자·창 함수(예: 3일 범위를 step 30초로 조회)는 수집 서버 전체에서 동시에 4개까지만 저장소를 조회합니다. 4개가 모두 조회 중이면 최대 10초 기다립니다. 그래도 차례가 오지 않으면 timeout 오류(HTTP 503) too many concurrent heavy queries; retry later 가 납니다. 잠시 뒤 다시 조회하세요. 시리즈당 행 수가 5,000 이하인 조회(대시보드의 일반 패널 등)는 기다리지 않습니다. 기준·동시 개수·대기 시간은 수집 서버 시스템 속성 promql.heavy.min.rows.per.series · promql.heavy.max.concurrent · promql.heavy.wait.ms(밀리초) 로 바꿀 수 있습니다. promql.heavy.max.concurrent 는 수집 서버를 시작할 때 한 번 읽습니다.

단일 시점의 값 하나만 필요하면 instant 쿼리(/api/v1/query)를 씁니다:

# 현재 / 1시간 전 시점의 힙 사용량
curl -G "http://{apm-server}/monitoring/api/v1/query" \
--data-urlencode "query=jvm_heap_heapUsed"
curl -G "http://{apm-server}/monitoring/api/v1/query" \
--data-urlencode "query=jvm_heap_heapUsed" \
--data-urlencode "time=now-1h"

메트릭 이름과 라벨​

APM 메트릭은 다섯 개 라벨 차원으로 구분됩니다. 쿼리의 필터·집계에 그대로 씁니다.

Label의미예시 값
__name__메트릭 이름 — {nameSpace}_{metricName}_{field} 형식jvm_heap_heapUsed, cpu_usage_cpuUsage
ip_addr에이전트가 설치된 호스트 IP192.168.80.190
agent_type에이전트 종류WAS, SYS, DBMS, WEB
instance_id인스턴스 식별자 (호스트 안에서 유일)apm-was-01, nginx-1
namespace메트릭 그룹jvm, transaction, cpu, memory

Prometheus 표준 호환 라벨도 자동 생성됩니다 — instance(= {ip_addr}:{instance_id}), job(= agent_type).

app_name 라벨은 인스턴스가 속한 애플리케이션 이름입니다. WAS 인스턴스는 에이전트가 보고한 애플리케이션 이름이 붙고, 사용자가 만든 커스텀 그룹 이름은 붙지 않습니다. 커스텀 그룹으로 거르려면 metric{app_name="<그룹 이름>"} 처럼 매처를 씁니다.

메트릭 이름은 {nameSpace}_{metricName}_{field} 한 가지 형식만 알면 됩니다 (마지막 _field는 생략 가능 — 생략하면 기본 field가 선택됩니다).

예시의미
jvm_heap_heapUsedJVM 힙의 사용량 field
jvm_heap_heapMax같은 메트릭의 최대치 field
cpu_usage_cpuUsageCPU 사용률
cpu_usage_systemCpuUsage시스템 전체 CPU 사용률

라벨 matcher는 표준 네 가지를 모두 지원하고, 여러 조건을 쉼표로 결합합니다:

metric{label="value"} # 일치
metric{label!="value"} # 불일치
metric{label=~"regex"} # 정규식 일치
metric{label!~"regex"} # 정규식 불일치

jvm_heap_heapUsed{ip_addr="192.168.80.190", instance_id=~"apm-was-.*", agent_type="WAS"}

정규식은 Prometheus 와 같은 RE2 문법(Go regexp)으로 해석하며, 값 전체와 일치해야 합니다. [[:alpha:]] 같은 POSIX 문자 클래스, (?P<name>…) 이름 있는 그룹, (?i) · (?m) · (?s) 플래그를 쓸 수 있습니다. RE2 가 받지 않는 다음 문법은 400 오류(invalid regular expression …: <이유>)를 돌려줍니다.

  • 전방·후방 탐색 (?=…) · (?!…) · (?<=…) · (?<!…), 원자 그룹 (?>…), 소유 수량자 *+ · ++ · ?+
  • 역참조 \1 · \k<name>
  • Java 전용 플래그와 이스케이프((?x) · (?u) · (?d), \h · \R · \Z · \e 등)
  • (?U) 플래그: RE2 에서는 반복의 최대·최소 일치를 서로 바꾸지만, 이 엔진은 같은 뜻으로 옮길 수 없어 400 으로 거절합니다. Prometheus 와 다른 점입니다.

Prometheus와 다른 점​

저장 방식이 다릅니다. Prometheus 는 counter 를 단조 증가하는 누적값으로 저장합니다. APM 은 필드마다 저장 방식이 다릅니다. 엔진은 measurement 와 필드를 함께 보고 저장 방식을 정한 뒤, 그 방식에 맞게 rate · irate · increase 를 계산합니다. 같은 필드 이름도 measurement 에 따라 저장 방식이 다릅니다. 예를 들어 apdex_total 은 변화량이고 memory_total 은 순간값, jvm_classes_total 은 누적값입니다.

저장 방식지표 예rate(x[N])increase(x[N])irate(x[N])경고
이미 비율 (초당 값, 시간 비율 %)tcp_activeOpens · interface_rxBytes · disk_diskReads · cpu_idle · WEB_stat_reqPerSec · MySQL qps*avg_over_time(x[N])avg_over_time(x[N]) × N초last_over_time(x[N])rate_alias
변화량 (직전 수집 이후 증가량, delta)apdex_count · gc_<수집기>_gcCount · 응답 상태 status* · MySQL diff*구간 delta 합계 ÷ N초구간 delta 합계마지막 delta ÷ 마지막 두 점 간격없음
누적값 (카운터 원값)jvm_classes_total · memory_swapPageIn · Nginx accepts · HAProxy ereq · MySQL comSelect 등 원값Prometheus 와 같음 (리셋 보정, 창 끝까지 늘려 추정)Prometheus 와 같음Prometheus 와 같음 (마지막 두 점)없음
순간값(gauge), 분류되지 않은 필드jvm_heap_heapUsed · memory_used · OpenTelemetry 지표Prometheus 와 같음Prometheus 와 같음Prometheus 와 같음없음
  • tps · minTps · maxTps (apdex_tps 등)는 초당 값이지만 트랜잭션이 있는 수집 구간에만 정수로 저장됩니다. 저장된 값을 평균하면 실제 처리량과 다릅니다. 그래서 같은 measurement 의 count(변화량)로 계산합니다. rate(apdex_tps[5m]) 는 rate(apdex_count[5m]) 와 같은 값이고 rate_alias 경고가 붙습니다. 처리량은 rate(apdex_count[5m]) 로 조회하세요.
  • 변화량은 직전 수집 이후의 증가량입니다. 그래서 구간 안 변화량의 합계가 구간의 증가량입니다. APM 은 이 값을 Prometheus extrapolatedRate 처럼 창 끝까지 늘려 추정하지 않습니다. 창 끝까지 늘려 추정하면 구간 첫 점의 증가량이 빠집니다.
  • 변화량의 irate 는 마지막 변화량을 마지막 두 점의 시각 차이로 나눕니다. apdex_count 처럼 트랜잭션이 없는 구간에 점이 없는 지표는 두 점 간격이 길어서 값이 작게 나옵니다.
  • 누적값 · 순간값 · 분류되지 않은 필드는 원 샘플을 읽어 Prometheus 와 같은 식으로 계산합니다. 원 샘플 상한(promql.raw.max.samples, 기본 1,000,000)이 적용됩니다. 순간값의 rate 는 뜻이 없는 값입니다. 순간값에는 avg_over_time · deriv 를 쓰세요.

이미 비율로 저장된 필드에는 avg_over_time · last_over_time 을 직접 쓰세요. rate() 를 쓴 값과 쓰지 않은 값은 단위가 같아도 값이 다릅니다. 함수 없이 조회한 값은 평가 시각 직전 5분의 평균이고, rate(x[1m]) 는 직전 1분의 평균입니다. avg_over_time(x[1m]) 은 rate(x[1m]) 와 같은 값이고 경고가 붙지 않습니다. increase(x[N]) 은 avg_over_time(x[N]) × N 과 같습니다.

range N 이 저장 간격 2초보다 짧으면, 이미 비율인 필드는 창을 2초로 넓혀 저장 값 하나를 그대로 씁니다. 이때 rate_short_window 경고가 붙습니다. 변화량 필드는 값을 그대로 계산하고 rate_short_window 경고만 붙입니다. 변화량 하나가 range 보다 긴 구간의 증가량이라 값이 커질 수 있습니다.

경고는 응답의 warnings 배열에 문장으로 들어갑니다. 시점 조회와 기간 조회 모두에 들어가고, Grafana 는 패널에 표시합니다.

rate(tcp_activeOpens[5m]): tcp_activeOpens is stored as a rate (SYS agent per-second value), so the result is the mean of the stored rate over the window
rate(tcp_activeOpens[1s]): the range is shorter than the stored rate window 2s (the 2s stored interval); the stored rate values were used as they are

계산 구간이 다릅니다. 시점 조회(/api/v1/query)와 기간 조회(/api/v1/query_range)는 아래 구간으로 값을 계산합니다.

쿼리시점 조회기간 조회
함수 없는 metric{...}평가 시각 직전 5분 구간의 집계값 (gauge 는 평균, delta counter 는 합계)각 시각 t 부터 step 동안 [t, t + step) 의 같은 방식 집계값
rate(metric[5m])(평가 시각 − 5분, 평가 시각] 구간을 위 표의 저장 방식대로 계산 (변화량은 합계 ÷ 300)각 시각 t 의 (t − 5분, t] 구간을 같은 방식으로 계산
increase(metric[5m])같은 구간을 위 표의 저장 방식대로 계산 (변화량은 합계)각 시각 t 의 (t − 5분, t] 구간을 같은 방식으로 계산
avg_over_time(metric[5m]) 등(평가 시각 − 5분, 평가 시각] 구간의 통계각 시각 t 의 (t − 5분, t] 구간 통계
deriv(metric[5m]) 등 원 샘플 창 함수(평가 시각 − 5분, 평가 시각] 구간의 원 샘플로 계산각 시각 t 의 (t − 5분, t] 구간 원 샘플로 계산
max_over_time(<식>[1h:1m]) 등 서브쿼리1분 배수 시각마다 계산한 <식> 값 중 (평가 시각 − 1시간, 평가 시각] 에 드는 값으로 계산각 시각 t 의 (t − 1시간, t] 에 드는 1분 배수 시각의 <식> 값으로 계산

기간 조회의 rate · irate · increase · *_over_time 은 Prometheus 처럼 시각 t 마다 (t − range, t] 구간을 계산하고, 값을 시각 t 에 붙입니다. 같은 시각의 시점 조회 값과 같습니다. APM 은 range 와 step 의 최대공약수 길이로 나눈 작은 구간을 InfluxDB 에서 읽어 시각마다 합칩니다.

다음 경우에는 step 구간 하나로 계산합니다. 시각 t 의 값은 [t, t + step) 구간의 값이고, rate 는 step 초로 나눕니다. 이때 응답의 warnings 에 window function <함수> approximated with step buckets (window <range>, step <step>) 가 들어갑니다. Grafana 는 이 경고를 패널에 표시합니다.

  • 시리즈 하나의 작은 구간 수 (end − start + range) ÷ 최대공약수 가 22,000 을 넘을 때. 상한은 수집 서버 시스템 속성 promql.window.max.buckets 로 바꿀 수 있습니다.
  • range 와 step 의 최대공약수가 1초보다 짧을 때 (예: [1500ms] 와 step 1초)
  • 계산으로 만든 지표 (cpu_usage_percent = 100 − idle)

경고를 없애려면 step 을 range 의 약수로 지정하거나(range 5m 이면 step 1m · 5m 등) 조회 기간을 줄입니다.

원 샘플 창 함수(delta · deriv · changes · quantile_over_time 등, 아래 "지원 함수" 참고)는 작은 구간으로 나누지 않고 구간 안의 샘플을 하나씩 읽습니다. 누적값 · 순간값 · 분류되지 않은 필드의 rate · irate · increase 와 변화량 필드의 irate 도 같은 방식으로 읽습니다. 기간 조회는 (start − range, end] 를 한 번 읽어 시각마다 구간을 나눕니다. step 구간으로 근사하지 않으므로 warnings 가 붙지 않습니다.

함수 없는 선택자의 기간 조회 값은 그 시각부터 한 step 동안의 집계입니다. 기존 APM 화면과 같은 값을 내도록 한 동작입니다. Prometheus 는 그 시각 이전의 마지막 샘플을 씁니다.

지원하는 것:

  • 라벨 matcher = · != · =~ · !~ (정규식은 RE2 문법이고 값 전체와 일치해야 합니다)
  • 집계 연산자 sum · avg · min · max · count · stddev · stdvar · topk · bottomk · quantile · count_values · group, by / without 절, 중첩 집계
  • 집계 파라미터의 스칼라 식(topk(2 * 3, …), quantile(0.5 + 0.4, …), topk(scalar(x), …))
  • offset · @ 수식자(metric offset 1h, rate(metric[5m] offset 1d), metric @ end())
  • 라벨 가공 함수 label_replace · label_join
  • rate · irate · increase, avg · min · max · sum · count · last · present · absent 의 *_over_time
  • 원 샘플 창 함수 delta · idelta · deriv · predict_linear · changes · resets · stddev_over_time · stdvar_over_time · quantile_over_time
  • 서브쿼리 <식>[<범위>:<해상도>] (창 함수의 범위 인자로 씁니다. 아래 "서브쿼리" 참고)
  • 수학 함수 abs · ceil · floor · round · clamp · clamp_min · clamp_max · sqrt · exp · ln · log2 · log10 · sgn
  • 삼각 함수 sin · cos · tan · asin · acos · atan · sinh · cosh · tanh · asinh · acosh · atanh · deg · rad · pi()
  • 정렬 sort · sort_desc, 시리즈 존재 확인 absent
  • 시각·스칼라 변환 time() · timestamp() · scalar() · vector(), 날짜 함수 minute · hour · day_of_week · day_of_month · day_of_year · days_in_month · month · year (기본 KST, promql.timezone 으로 변경)
  • 산술 연산(+ - * / % ^ atan2), 비교 연산(== != > < >= <=)과 bool 수식자, 단항 마이너스
  • 벡터 매칭 on(...) · ignoring(...), 다대일·일대다 매칭 group_left · group_right
  • 논리 연산자 and · or · unless
  • 16진수 숫자(0x10 = 16), 시점 조회의 문자열 리터럴("abc", 결과 형식 string. 기간 조회에서는 bad_data)
  • HTTP API (/api/v1/query, /api/v1/query_range, /api/v1/series, /api/v1/labels 등)

지원하지 않는 것 — 쿼리 문법 항목을 쓰면 bad_data 오류(HTTP 400)가 납니다.

항목비고
histogram_quantile()APM 은 le 라벨이 붙은 히스토그램 버킷을 저장하지 않습니다. 응답 시간은 apdex_avgRT · apdex_maxRT 같은 field 를 조회하세요
mad_over_time() · holt_winters() 등 위 목록에 없는 함수오류 메시지에 함수 이름이 나옵니다
함수 없이 쓴 서브쿼리(metric[1h:1m]), rate · irate · increase 의 서브쿼리 인자, 서브쿼리의 @서브쿼리는 창 함수의 범위 인자로만 씁니다. APM 의 rate 계열은 저장된 필드의 저장 방식을 보고 계산하므로 계산된 값에는 쓸 수 없습니다. 오류 메시지에 이유가 나옵니다
쿼리의 __name__ 정규식, 지표 이름이 없는 선택자 ({__name__=~"a|b"}, {ip_addr="..."})지표 이름을 지정하세요. {__name__="x"} 는 x 와 같게 처리합니다. /api/v1/series 와 match[] 에서는 __name__ 정규식을 쓸 수 있습니다(맞는 지표 이름 20개까지)

쿼리 문법이 아닌 기능 중에서는 Recording / Alerting rules 를 지원하지 않습니다. 장기간 조회 자동 롤업도 적용하지 않습니다. 수 주 이상 조회할 때는 step 을 크게 지정하세요.

참고 서로 다른 지표끼리 연산하면(a / b) 결과가 비어 있습니다. 기본 매칭은 __name__ 을 뺀 모든 라벨을 비교하고, 두 지표는 namespace · metric_name 라벨이 다르기 때문입니다. jvm_heap_heapUsed / on(instance) cpu_usage_cpuUsage 처럼 비교할 라벨을 지정하세요. 같은 지표의 field 끼리(jvm_heap_heapUsed / jvm_heap_heapMax)는 지정하지 않아도 됩니다.


지원 함수​

instant vector · range vector · scalar 를 지원합니다. range vector(metric[5m])는 rate 같은 함수의 인자로 씁니다. 문자열 리터럴은 label_replace · label_join · count_values 의 인자와 시점 조회의 결과로만 씁니다.

Rate / Counter 함수 — range vector → instant vector:

rate(metric[5m]) # 초당 평균 변화율 (필드의 저장 방식별 계산은 "Prometheus와 다른 점" 참고)
irate(metric[5m]) # 마지막 두 샘플 기반 순간 변화율
increase(metric[5m]) # 구간 전체 증가량

over_time 함수군 — 구간 통계:

avg_over_time(metric[1h]) min_over_time(metric[1h]) max_over_time(metric[1h])
sum_over_time(metric[1h]) count_over_time(metric[1h]) last_over_time(metric[1h])
present_over_time(metric[1h]) absent_over_time(metric[1h])

present_over_time 은 구간에 값이 있는 시리즈마다 1 입니다. absent_over_time 은 구간에 값이 있는 시리즈가 하나도 없을 때 1 입니다. 두 함수는 count_over_time 과 같은 방식으로 조회합니다.

원 샘플 창 함수 — 구간 안의 샘플을 하나씩 읽어 Prometheus 와 같은 식으로 계산합니다:

delta(jvm_heap_heapUsed[10m]) # 구간의 처음·끝 샘플 값 차이를 구간 길이에 맞게 늘린 값
idelta(jvm_heap_heapUsed[5m]) # 마지막 두 샘플의 값 차이
deriv(jvm_heap_heapUsed[30m]) # 초당 변화량(최소제곱 회귀의 기울기)
predict_linear(jvm_heap_heapUsed[1h], 4 * 3600) # 4시간(14,400초) 뒤 예상값
changes(jvm_heap_heapUsed[1h]) # 연속한 두 샘플의 값이 다른 횟수
resets(jvm_heap_heapUsed[1h]) # 연속한 두 샘플에서 값이 줄어든 횟수
stddev_over_time(jvm_heap_heapUsed[1h]) # 표준편차
stdvar_over_time(jvm_heap_heapUsed[1h]) # 분산
quantile_over_time(0.95, jvm_heap_heapUsed[1h]) # 구간 샘플의 95 백분위수
  • delta · idelta · deriv · predict_linear 은 샘플이 2개 이상, 나머지는 1개 이상인 구간에만 값이 있습니다. 샘플이 모자란 시각은 결과에 점이 없습니다.
  • delta 는 처음 샘플이 구간 시작에서 평균 샘플 간격의 1.1배 안에 있으면 구간 시작까지 늘리고, 그보다 멀면 평균 간격의 절반만큼 늘립니다. 끝 샘플과 구간 끝도 같습니다.
  • predict_linear(v[r], s) 는 평가 시각에서 s 초 뒤의 값입니다. s 와 quantile_over_time 의 φ 에는 스칼라 식(4 * 3600, scalar(x))을 씁니다. 기간 조회에서 값이 스텝마다 다르면 스텝마다 그 값으로 계산합니다. φ 가 0 보다 작으면 -Inf, 1 보다 크면 +Inf 입니다.
  • stddev_over_time · stdvar_over_time 은 구간 샘플 전체를 모집단으로 본 표준편차·분산입니다.
  • 결과에서는 __name__ 라벨이 빠집니다.
  • 한 쿼리가 읽는 원 샘플은 모두 합쳐 1,000,000개까지입니다. 넘으면 bad_data 오류(HTTP 400) query reads too many samples (<읽은 수> > <상한>); use a shorter range or fewer series 가 나고, 근사값을 내지 않습니다. 2초마다 수집하는 지표는 시리즈 하나가 하루에 43,200개입니다. 상한은 수집 서버 시스템 속성 promql.raw.max.samples 로 바꿀 수 있습니다.
  • counter 에 쓸 때: APM 은 counter 를 필드마다 다른 방식으로 저장합니다(위 "Prometheus와 다른 점" 의 저장 방식 표). delta · idelta · resets · changes 를 변화량(delta)으로 저장된 지표(apdex_count · gc_<수집기>_gcCount 등)에 쓰면 저장된 변화량을 계산합니다. counter 의 증가량과 증가율은 increase · rate 로 조회하세요.

서브쿼리 — <식>[<범위>:<해상도>] 는 <식> 을 해상도 간격으로 계산한 값을 range vector 로 씁니다. 창 함수의 범위 인자 자리에 씁니다:

max_over_time(sum(jvm_heap_heapUsed)[1h:1m]) # 최근 1시간 동안 힙 합계의 최댓값
avg_over_time((jvm_heap_heapUsed / jvm_heap_heapMax)[1h:1m]) # 힙 사용률의 1시간 평균
deriv(sum(jvm_heap_heapUsed)[30m:1m]) # 힙 합계의 초당 변화량
max_over_time(rate(gc_G1_Young_Generation_gcCount[5m])[1d:5m] offset 1d) # 어제 하루 동안 GC 빈도의 최댓값
  • 서브쿼리를 받는 함수는 *_over_time(avg · min · max · sum · count · last · present · absent)과 원 샘플 창 함수 9개입니다.
  • 해상도를 생략하면([1h:]) 1분입니다.
  • <식> 은 유닉스 시각 기준으로 해상도의 배수인 시각마다 계산합니다. 조회 시작 시각에 맞추지 않으므로, 대시보드를 새로 고쳐도 같은 시각의 값은 바뀌지 않습니다.
  • 시각 t 의 값은 (t − 범위, t] 에 드는 계산 값으로 구합니다. offset 을 붙이면 (t − offset − 범위, t − offset] 입니다.
  • <식> 안의 선택자는 각 계산 시각 τ 직전 5분 (τ − 5분, τ] 의 마지막 샘플을 씁니다(Prometheus 와 같습니다). 해상도가 수집 간격보다 짧으면 같은 샘플 값이 반복됩니다. 5분 넘게 샘플이 없으면 그 시각에는 값이 없습니다. 함수 없는 선택자의 기간 조회 값(step 구간 집계)과 다릅니다.
  • 값이 없는 시각은 창에 넣지 않습니다. 0 으로 채우지 않습니다.
  • 서브쿼리 안에 서브쿼리를 쓸 수 있습니다(max_over_time(sum_over_time(x[30s:10s])[5m:10s])).
  • absent_over_time(<서브쿼리>) 의 결과 라벨은 {} 입니다(Prometheus 와 같습니다). 다른 함수의 라벨 규칙은 일반 창 함수와 같습니다.
  • 서브쿼리 하나가 계산하는 점(시리즈 수 × 계산 시각 수)은 50,000,000개까지입니다. 넘으면 bad_data 오류(HTTP 400) subquery evaluates too many points (<점 수> > <상한>); use a coarser resolution 가 납니다. 계산 전에 시각 수로 한 번, 계산 뒤에 점 수로 한 번 확인합니다. 상한은 수집 서버 시스템 속성 promql.subquery.max.points 로 바꿀 수 있습니다.
  • 계산으로 만든 지표(cpu_usage_percent 등)는 서브쿼리 안에서 쓸 수 없습니다.
  • 서브쿼리 안의 값은 근사하지 않습니다. 다음 경우에는 bad_data 오류(HTTP 400)가 납니다.
    • 서브쿼리 안의 선택자가 시리즈 하나에서 읽는 작은 구간 수 (조회 기간 + 범위 + 5분) ÷ (5분과 해상도의 최대공약수) 가 22,000(promql.window.max.buckets)을 넘을 때. 오류 문구는 subquery needs too many buckets per series (<구간 수> > <상한>) 입니다. 계산을 시작하기 전에 판단합니다. 해상도를 크게 하거나 범위를 줄이세요.
    • 5분과 해상도의 최대공약수가 1초보다 짧을 때 (예: [1m:700ms])
    • 계산으로 만든 지표를 서브쿼리 안에서 쓸 때, 서브쿼리 안의 창 함수를 정확히 계산할 수 없을 때. 오류 문구는 subquery cannot be evaluated exactly: … 입니다.

집계 연산자 — sum · avg · min · max · count · stddev · stdvar · topk(N, …) · bottomk(N, …) · quantile(0.95, …) · count_values("라벨", …) · group. by / without 절로 그룹화합니다. by 결과에는 나열한 라벨만 남고, without 결과에서는 나열한 라벨과 __name__ 이 빠집니다:

avg by (instance) (jvm_heap_heapUsed) # 인스턴스별 평균
sum without (user_key) (jvm_heap_heapUsed) # user_key 만 제외하고 그룹화
topk(5, rate(gc_G1_Young_Generation_gcCount[5m])) # GC 빈도 상위 5개 인스턴스
count(count by (ip_addr) (jvm_heap_heapUsed)) # 호스트 수
count_values("heap_gib", round(jvm_heap_heapMax / 1024 / 1024 / 1024)) # 최대 힙(GiB)별 인스턴스 수

topk · bottomk 의 N 과 quantile 의 값에는 스칼라 식(2 * 3, scalar(x))을 씁니다. 기간 조회에서 값이 스텝마다 다르면 스텝마다 그 값을 씁니다. N 은 소수점 아래를 버리고, 1 보다 작거나 NaN 이면 그 스텝의 결과가 없습니다. 벡터를 넣으면 bad_data 오류가 납니다. scalar() 로 감싸세요. count_values 의 라벨 값은 Prometheus 와 같은 형식입니다(1, 0.5, 1000000, NaN, +Inf).

시점 이동 — offset · @:

jvm_heap_heapUsed offset 1h # 1시간 전 값
rate(gc_G1_Young_Generation_gcCount[5m] offset 1d) # 하루 전 같은 시각의 GC 빈도
jvm_heap_heapUsed @ 1700000000 # 고정 시각(unix 초)의 값
jvm_heap_heapUsed @ end() # 조회 끝 시각의 값

offset 은 선택자나 범위 선택자, 서브쿼리 바로 뒤에 씁니다. 함수 결과나 괄호 식 뒤에 쓰면 bad_data 오류가 납니다. 음수(offset -5m)는 미래 방향으로 옮깁니다. @ 는 그 시각 한 시점의 값을 읽습니다. 기간 조회에서는 모든 스텝이 같은 값입니다. @ start() · @ end() 는 기간 조회의 시작·끝 시각이고, 시점 조회에서는 둘 다 평가 시각입니다. offset 과 @ 는 함께 쓸 수 있고 순서는 상관없습니다.

라벨 가공 — label_replace · label_join:

# instance_id 의 "-" 앞부분을 app 라벨로
label_replace(jvm_heap_heapUsed, "app", "$1", "instance_id", "(.*)-.*")
# ip_addr 와 instance_id 를 ":" 로 이어 host 라벨로
label_join(jvm_heap_heapUsed, "host", ":", "ip_addr", "instance_id")

label_replace 의 정규식은 라벨 matcher 와 같은 RE2 문법이며, 원본 라벨 값 전체와 일치해야 합니다. 일치하지 않는 시리즈는 그대로 남습니다. 치환 문자열에는 $1 · ${1} · $name · ${name} · $$ 를 씁니다. 이름 그룹은 (?P<name>…) 로 정의합니다. 결과 값이 빈 문자열이면 그 라벨을 지웁니다. label_replace 결과에 라벨이 모두 같은 시리즈가 둘 이상 생기면 bad_data 오류가 납니다.

수학·산술·비교:

abs(metric) ceil(metric) floor(metric) round(metric) round(metric, 0.5)
clamp(metric, 0, 100) clamp_min(metric, 0) clamp_max(metric, 100)
sqrt(metric) exp(metric) ln(metric) log2(metric) log10(metric) sgn(metric)
sin(metric) cos(metric) tan(metric) asin(metric) acos(metric) atan(metric)
sinh(metric) cosh(metric) tanh(metric) asinh(metric) acosh(metric) atanh(metric)
deg(metric) rad(metric) pi()

jvm_heap_heapUsed / jvm_heap_heapMax
jvm_heap_heapUsed / on(instance) cpu_usage_cpuUsage
rate(metric[5m]) * 60
jvm_heap_heapUsed > 1024 * 1024 * 1024 # 1GB 초과 시리즈만 반환
jvm_heap_heapUsed > bool 1024 * 1024 * 1024 # 시리즈마다 1(초과) 또는 0

산술 연산과 수학 함수, rate · irate · increase · *_over_time · 원 샘플 창 함수의 결과에서는 __name__ 라벨이 빠집니다(last_over_time 은 남깁니다). 기간 조회의 topk · bottomk 는 스텝마다 순위를 다시 매깁니다. 시리즈는 뽑힌 스텝의 점만 가지므로 그래프의 선이 중간에 끊길 수 있습니다(Prometheus 와 같습니다). 비교 필터(bool 없음)는 조건에 맞는 시리즈만 원래 라벨 그대로 남깁니다. 0 으로 나누면 결과 값이 +Inf · -Inf · NaN 이 됩니다. 수학 함수에 정의역 밖의 값을 넣어도 시리즈는 남고 값이 NaN · -Inf 가 됩니다(sqrt(-1) = NaN, ln(0) = -Inf). pi() 는 스칼라 π 입니다.

정렬·존재 확인 — sort · sort_desc · absent:

sort_desc(jvm_heap_heapUsed) # 값이 큰 시리즈부터
absent(jvm_heap_heapUsed{instance_id="api-53-x"}) # 시리즈가 없으면 {instance_id="api-53-x"} 1
absent_over_time(jvm_heap_heapUsed{instance_id="api-53-x"}[10m]) # 10분 동안 값이 없으면 1

sort · sort_desc 는 시점 조회 결과의 순서를 값 기준으로 바꿉니다. NaN 은 맨 뒤에 오고, 값이 같으면 라벨 순서입니다. 기간 조회에서는 순서를 바꾸지 않습니다(Prometheus 와 같습니다). absent 는 인자에 값이 있는 시리즈가 하나도 없는 시각에 1 을 돌려줍니다. 값이 있으면 결과가 비어 있습니다. 결과 라벨은 인자 선택자의 = matcher 로 만듭니다(__name__ 제외, app_name 포함). 같은 라벨 이름에 matcher 가 둘 이상이면 그 라벨은 넣지 않고, 인자가 선택자가 아니면(absent(sum(…))) 라벨이 없습니다.

시각·스칼라 변환 — time · scalar · vector · 날짜 함수:

time() # 평가 시각(unix 초). 기간 조회에서는 스텝 시각
time() - timestamp(jvm_heap_heapUsed) # 마지막으로 수집한 뒤 지난 초
scalar(sum(jvm_heap_heapUsed)) # 시리즈 하나짜리 벡터를 스칼라로
jvm_heap_heapUsed > scalar(avg(jvm_heap_heapUsed)) # 스텝마다 그 시각의 전체 평균보다 큰 시리즈
topk(scalar(count(jvm_heap_heapUsed) / 7), jvm_heap_heapUsed) # 인스턴스 수의 1/7 만큼 상위
vector(time()) # 스칼라를 라벨 없는 시리즈로
hour() # 평가 시각의 시(0–23, 기본 KST)
year(vector(1700000000)) # unix 초 1700000000 의 연도 = 2023
  • time() 은 평가 시각의 unix 초입니다. 기간 조회에서는 스텝마다 그 스텝의 시각입니다.
  • scalar(v) 는 스텝마다 v 에 값이 있는 시리즈가 정확히 하나면 그 값이고, 없거나 둘 이상이면 NaN 입니다.
  • vector(s) 는 라벨 없는 시리즈 하나이고, 값은 스텝마다 s 의 값입니다.
  • 날짜 함수는 기본으로 KST(Asia/Seoul) 기준입니다. minute(0–59) · hour(0–23) · day_of_week(0 = 일요일 ~ 6) · day_of_month(1–31) · day_of_year(1–366) · days_in_month(28–31) · month(1–12) · year. KST 오전 9시의 hour() 는 9 입니다.
  • 시간대는 수집 서버의 JVM 시스템 속성 promql.timezone 으로 바꿉니다. 값은 Asia/Seoul, UTC 같은 시간대 이름입니다(예: -Dpromql.timezone=UTC). 잘못된 값이면 경고 로그를 남기고 KST 로 계산합니다.
  • Prometheus 는 UTC 로 계산합니다. 그래서 기본 설정에서는 같은 쿼리의 결과가 Prometheus 와 9시간 다릅니다. Prometheus 와 같은 값이 필요하면 promql.timezone=UTC 로 둡니다. observ(Cache PromQL)도 기본값이 KST 입니다.
  • 날짜 함수에 인자가 없으면 평가 시각(기간 조회는 스텝 시각)으로 계산한 라벨 없는 시리즈입니다. 벡터 인자를 주면 각 값을 unix 초로 보고 계산하고, 결과에서 __name__ 이 빠집니다. 소수점 아래 초는 버리고 NaN · ±Inf 는 그대로 둡니다.
  • 스칼라는 스텝마다 값이 다를 수 있습니다. 스칼라를 받는 자리(산술·비교 연산, round · clamp · clamp_min · clamp_max, predict_linear 의 초, quantile_over_time 의 φ, topk · bottomk · quantile 의 파라미터)는 스텝마다 그 스텝의 값을 씁니다. clamp 의 최솟값이 최댓값보다 큰 스텝은 결과가 없습니다.
  • 쿼리 결과가 스칼라이면 시점 조회는 결과 형식 scalar, 기간 조회는 라벨 없는 시리즈 하나로 돌려줍니다.
  • timestamp(v) 는 v 가 선택자(괄호로 감싼 것 포함)이면 저장된 원 샘플의 시각입니다. 시각마다 직전 5분((t − offset − 5분, t − offset])의 마지막 원 샘플 시각을 unix 초로 돌려줍니다. 밀리초는 소수점 아래로 나옵니다. 5분 동안 샘플이 없으면 그 시각의 점이 없습니다(Prometheus 와 같습니다).
  • timestamp(v) 는 원 샘플을 읽으므로 원 샘플 상한(위 "원 샘플 창 함수" 참고)을 적용합니다. 긴 기간 조회에서 상한을 넘으면 bad_data 오류가 납니다. @ 를 쓰면 모든 시각에서 같은 창을 씁니다. 서브쿼리 안에서는 안쪽 계산 시각마다 같은 규칙입니다.
  • v 가 선택자가 아니면(timestamp(sum(x)), timestamp(rate(x[5m]))) 각 점의 시각, 곧 평가 시각(기간 조회는 스텝 시각)입니다. 결과에서 __name__ 이 빠집니다. 범위 벡터(timestamp(x[5m]))를 넣으면 bad_data 오류가 납니다.

논리 연산자 — and · or · unless:

jvm_heap_heapUsed and on(instance) jvm_heap_heapMax > 1024 * 1024 * 1024 # 최대 힙이 1GB 를 넘는 인스턴스의 힙 사용량
jvm_heap_heapUsed unless jvm_heap_heapUsed{instance_id="khan11"} # khan11 을 뺀 나머지
rate(gc_G1_Young_Generation_gcCount[5m]) > 1 or rate(gc_G1_Young_Generation_gcCount[5m]) < 0.1 # 두 조건 중 하나에 맞는 시리즈
  • a and b 는 같은 시각에 매칭 키가 같은 b 의 점이 있는 a 의 점만 남깁니다. 값과 라벨은 a 의 것입니다.
  • a unless b 는 같은 시각에 매칭 키가 같은 b 의 점이 없는 a 의 점만 남깁니다.
  • a or b 는 a 의 모든 점에, 같은 시각에 매칭 키가 같은 a 의 점이 없는 b 의 점을 더합니다. 라벨은 각자 그대로입니다.

매칭 키는 산술 연산과 같습니다. 기본은 __name__ 을 뺀 모든 라벨이고, on(...) · ignoring(...) 으로 바꿉니다. 결과에는 __name__ 이 남습니다. 기간 조회에서는 시각마다 따로 판단합니다. 피연산자가 스칼라이거나 bool · group_left · group_right 와 함께 쓰면 bad_data 오류가 납니다.

다대일 매칭 — group_left · group_right:

jvm_heap_heapUsed / on(ip_addr) group_left cpu_usage_cpuUsage # 호스트 하나에 인스턴스가 여럿일 때
jvm_heap_heapUsed / on(instance) group_left(app_name) jvm_heap_heapMax # 오른쪽의 app_name 라벨을 결과에 복사

group_left 는 왼쪽에 매칭 키가 같은 시리즈가 여럿이고 오른쪽에는 하나일 때 씁니다. group_right 는 좌우가 반대입니다. on(...) · ignoring(...) 뒤에 쓰고, 산술 연산과 비교 연산에만 쓸 수 있습니다.

  • 결과 라벨은 여러 시리즈 쪽(group_left 는 왼쪽)의 라벨입니다. 일대일 매칭과 달리 on(...) 으로 줄이지 않습니다. 산술 연산과 bool 비교에서는 __name__ 이 빠집니다.
  • 괄호 안에 나열한 라벨은 시리즈가 하나인 쪽에서 복사합니다. 그쪽에 그 라벨이 없으면 결과에서 지웁니다.
  • 시리즈가 하나여야 하는 쪽에 같은 시각, 같은 매칭 키의 시리즈가 둘 이상이면 bad_data 오류(many-to-many matching not allowed)가 납니다. 결과 라벨이 같은 시리즈가 둘 이상 생겨도 오류가 납니다.
  • 비교 필터(bool 없음)의 결과 값은 왼쪽 피연산자의 값입니다(Prometheus 와 같습니다).
  • 오른쪽 피연산자를 괄호로 감쌀 때는 group_left() (a + b) 처럼 빈 라벨 목록을 먼저 씁니다. Prometheus 는 group_left 바로 뒤의 괄호를 라벨 목록으로 읽습니다.

연산자 우선순위 — 위에 있는 연산자가 먼저 묶입니다(Prometheus 와 같습니다).

순서연산자묶는 방향
1^오른쪽부터 (2 ^ 3 ^ 2 = 2 ^ (3 ^ 2) = 512)
2단항 + · -(-2 ^ 2 = -(2 ^ 2) = -4)
3* · / · % · atan2왼쪽부터
4+ · -왼쪽부터
5== · != · <= · < · >= · >왼쪽부터
6and · unless왼쪽부터
7or왼쪽부터

2026-10-05 이전 버전은 -2 ^ 2 를 4 로, 2 ^ 3 ^ 2 를 64 로 계산했습니다. 이런 식을 쓰는 대시보드는 값이 바뀝니다.

a atan2 b 는 점마다 b 에 대한 a 의 아크탄젠트(라디안, −π ~ π)입니다. 산술 연산과 같이 on(...) · ignoring(...) · group_left · group_right 를 쓸 수 있고 결과에서 __name__ 이 빠집니다. bool 과 함께 쓰면 문법 오류(bad_data)입니다.


Metric Explorer​

브라우저에서 PromQL을 인터랙티브하게 실행하는 UI입니다 — 위 여는 법의 주소로 접속합니다.

영역기능
메트릭 선택 드롭다운등록된 메트릭 자동 발견 (__name__ 기준)
PromQL 쿼리 입력직접 입력 — 드롭다운에서 고르면 자동으로 채워짐
Label 필터 패널ip_addr · agent_type · instance_id · namespace 별 드롭다운
집계 함수 선택sum · avg · topk · quantile 등
시간 범위최근 5m ~ 7d 빠른 버튼 + 커스텀 범위
StepAuto / 15s / 1m / 5m / 10m / 30m / 1h
결과 시각화line / area / bar 차트 + raw 값 테이블
API URL 복사현재 쿼리를 /api/v1/query_range URL로 복사 — Grafana 등 외부 연동용

30초 만에 첫 차트를 만들어 봅니다:

  1. 메트릭 드롭다운에서 jvm_heap_heapUsed 선택
  2. Label 필터에서 agent_type=WAS 선택
  3. 시간 범위 1h 클릭, Step은 Auto 유지
  4. Run 클릭 → WAS 인스턴스들의 1시간 힙 사용량 그래프가 표시됩니다

참고 Step은 보통 Auto면 충분합니다. 작은 step + 긴 범위는 서버 부하가 커집니다.

Grafana 연동 — 같은 API를 Grafana의 Prometheus 데이터소스로 연결할 수 있습니다:

URL: http://{apm-server}/monitoring
Access: Server (default)

Grafana가 /api/v1/query, /api/v1/query_range, /api/v1/labels 등을 자동으로 호출합니다 — 기존 대시보드·알림 자산을 그대로 재사용하세요.


HTTP API 요약​

MethodPath용도
GET / POST/api/v1/query단일 시점(instant) 쿼리
GET / POST/api/v1/query_range시간 범위(range) 쿼리
GET/api/v1/seriesseries 메타데이터
GET/api/v1/labelslabel 이름 목록
GET/api/v1/label/{name}/values특정 label의 값 목록
GET/api/v1/metadata메트릭 메타데이터
GET/api/v1/metric-explorerMetric Explorer UI

파라미터 — query(필수), instant는 time, range는 start · end · step(생략 시 자동 계산). /series · /labels · /label/{name}/values 는 match[] · start · end · limit 를 받습니다. match[] 를 주면 그 선택자에 맞는 시리즈의 라벨 이름·값만 돌려줍니다(Grafana 변수 label_values(metric, label) 가 이 호출을 씁니다). limit 은 정렬한 결과의 앞에서 자를 개수입니다(0 또는 생략은 제한 없음, 음수는 bad_data). 탐색용 호출:

# 사용 가능한 메트릭 전체 목록 (~250개)
curl "http://{apm-server}/monitoring/api/v1/label/__name__/values"

# label 이름 목록 / 특정 label 의 값
curl "http://{apm-server}/monitoring/api/v1/labels"
curl "http://{apm-server}/monitoring/api/v1/label/agent_type/values"

# 특정 지표에 있는 라벨 / 그 지표의 instance 값 10개
curl -G "http://{apm-server}/monitoring/api/v1/labels" --data-urlencode "match[]=jvm_heap_heapUsed"
curl -G "http://{apm-server}/monitoring/api/v1/label/instance/values" \
--data-urlencode "match[]=jvm_heap_heapUsed" --data-urlencode "limit=10"

match[] 에 선택자를 여럿 주었을 때 하나라도 저장소 조회에 실패하면, 일부 결과를 돌려주지 않고 요청 전체가 오류입니다(Prometheus 와 같습니다).

HTTP 오류 상태 — 오류 응답의 errorType 과 HTTP 상태는 unavailable 을 빼고 Prometheus 와 같습니다. 모든 API 에 같은 규칙을 씁니다.

errorTypeHTTP원인
bad_data400문법 오류, 지원하지 않는 함수, 조회 크기 상한 초과, 잘못된 파라미터
execution422그 밖의 실행 오류(수집 서버 내부 오류)
internal500저장소(InfluxDB)가 오류로 응답함. 메시지는 InfluxDB query failed: … 로 시작합니다
timeout503저장소가 제한 시간 안에 응답하지 않음, 또는 무거운 조회의 차례가 10초 안에 오지 않음
unavailable503저장소에 연결하지 못함. Prometheus 는 이 errorType 에 500 을 씁니다. APM 은 다시 시도하면 되는 오류라서 503 을 씁니다

503 은 잠시 뒤 다시 시도하면 되는 오류입니다.


자주 쓰는 쿼리 모음​

메트릭 이름은 일반 패턴 기준 예시입니다 — 운영 환경의 정확한 이름은 Metric Explorer로 확인하세요.

JVM / WAS:

jvm_heap_heapUsed{agent_type="WAS"} # 전체 WAS 의 현재 힙 사용량
avg_over_time(jvm_heap_heapUsed[5m]) # 힙 사용량 5분 평균
topk(5, jvm_heap_heapUsed) # 힙 사용 상위 5개 인스턴스
(jvm_heap_heapUsed / jvm_heap_heapMax) > 0.8 # 힙 사용률 80% 초과
sum_over_time(gc_G1_Young_Generation_gcTime[1h]) # GC 시간 합계 (1시간)
rate(gc_G1_Young_Generation_gcCount[5m]) # 초당 GC 횟수
datasource_pool_active{agent_type="WAS"} # 사용 중 DataSource 연결 수

시스템:

topk(10, cpu_usage_cpuUsage{agent_type="SYS"}) # CPU 상위 10개 호스트
cpu_usage_systemCpuUsage # 시스템 전체 CPU
avg_over_time(cpu_usage_cpuUsage[1h]) # 인스턴스별 1시간 평균 CPU

호스트 단위 집계:

avg by (ip_addr) (jvm_heap_heapUsed) # 호스트별 평균 힙
count by (agent_type) (jvm_heap_heapUsed) # agent_type 별 인스턴스 수
jvm_heap_heapUsed{ip_addr="192.168.80.190"} # 특정 IP 의 힙 사용량

잘 안될 때​

증상점검
메트릭 이름을 모르겠음Metric Explorer 드롭다운 또는 /api/v1/label/__name__/values에서 실제 이름 확인
결과가 비어 있음label 값 오타 — /api/v1/label/{name}/values로 가능한 값 확인, agent_type 대소문자 확인
Metric Explorer 로그인이 안 됨API 접근 키 필요 — 설정 ▸ 사용자에서 키 생성·복사
rate() 값이 예상과 다름필드의 저장 방식에 따라 계산이 다름 — 위 "Prometheus와 다른 점" 의 저장 방식 표 확인. 이미 비율인 필드는 함수 없이 조회한 값(직전 5분 평균)과 rate(x[N])(직전 N 평균)이 다름
응답 warnings 에 … is stored as a rate … (rate_alias)필드가 이미 비율로 저장되어 rate 를 avg_over_time, irate 를 last_over_time 으로 계산함 — avg_over_time · last_over_time 을 직접 쓰면 경고가 붙지 않음. tps 계열은 count 로 계산함
응답 warnings 에 the range is shorter than … (rate_short_window)range 가 저장 간격 2초보다 짧음 — range 를 2초 이상으로 지정
합계·평균이 안 맞음함수 없는 조회는 직전 5분(시점 조회) 또는 각 시각부터 step 동안(기간 조회)의 평균·합계 — 원하는 구간을 sum_over_time / avg_over_time으로 명시
응답 warnings 에 window function … approximated with step buckets창 함수를 step 구간 하나로 계산함 — step 을 range 의 약수로 지정하거나 조회 기간을 줄임 (위 "계산 구간" 참고)
query selects too many series 오류선택자·창 함수 하나가 읽는 시리즈가 상한(2,000,000 ÷ 시리즈당 행 수)을 넘음 — step 을 크게 하거나 조회 기간을 줄이거나 라벨로 시리즈를 좁힘 (위 "기간을 지정해 조회하기" 참고)
query reads too many rows 오류한 쿼리가 읽는 행의 합계가 상한(기본 8,000,000)을 넘음 — step 을 크게 하거나 조회 기간을 줄이거나 라벨로 시리즈를 좁힘
too many concurrent heavy queries; retry later 오류 (HTTP 503)시리즈당 5,000행이 넘는 조회가 동시에 4개 실행 중이고 10초 안에 차례가 오지 않음 — 잠시 뒤 다시 조회하거나 step 을 크게 지정
internal 오류 (HTTP 500) InfluxDB query failed: …저장소가 오류로 응답함 — 메시지의 InfluxDB 오류 문구와 수집 서버 로그에 남은 InfluxQL 을 함께 확인
timeout · unavailable 오류 (HTTP 503)저장소가 제한 시간 안에 응답하지 않았거나 연결되지 않음 — InfluxDB 상태를 확인하고 잠시 뒤 다시 조회. 시간 초과가 계속되면 조회 기간을 줄이거나 step 을 크게 지정
query reads too many samples 오류원 샘플을 읽는 계산(원 샘플 창 함수, 원 샘플로 계산하는 rate 계열, timestamp())이 읽는 샘플 수가 상한(기본 1,000,000)을 넘음 — range 나 조회 기간을 줄이거나 라벨로 시리즈를 좁힘
subquery evaluates too many points 오류서브쿼리가 계산하는 점이 상한(기본 50,000,000)을 넘음 — 해상도를 크게 하거나 조회 기간·범위를 줄임
subquery needs too many buckets per series 오류서브쿼리 안의 선택자가 읽는 작은 구간이 시리즈당 상한(기본 22,000)을 넘음 — 해상도를 크게 하거나 범위·조회 기간을 줄임
cannot be evaluated exactly 오류 (subquery … cannot be evaluated exactly)서브쿼리 안의 값을 해상도대로 정확히 계산할 수 없음 — 해상도를 크게 하거나 범위를 줄임. 계산으로 만든 지표는 서브쿼리 안에서 쓸 수 없음 (위 "서브쿼리" 참고)
두 지표의 연산 결과가 비어 있음라벨이 달라 매칭되지 않음 — on(instance) 처럼 비교할 라벨을 지정
bad_data 오류 (HTTP 400)미지원 문법·함수 — 오류 메시지의 함수 이름과 위 "지원하지 않는 것" 표 확인
histogram_quantile이 안 됨미지원 — APM 은 le 버킷을 저장하지 않습니다. apdex_avgRT · apdex_maxRT 같은 응답 시간 field 를 직접 조회
장기간 조회가 느림step을 크게(30m~1h) 지정 — 작은 step + 긴 범위는 부하가 큽니다

관련 문서​

이 장은 OPENMARU APM API 연동 가이드 7장에도 같은 내용으로 실려 있습니다. 세션 쿠키를 쓰는 JSON API(그래프 데이터·구성 정보·사용자 관리)와 함께 보려면 그 가이드를 보십시오.