본문으로 건너뛰기

7. PromQL 연동

이미 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에는 없는 편의 기능)

어떤 메트릭이 어떤 의미인지는 OPENMARU APM 사용자 매뉴얼 R2. 차트 지표 레퍼런스와 OPENMARU APM 사용자 매뉴얼 E3. 지표의 의미를 보세요. 콘솔 안에서 차트를 모아 보려면 OPENMARU APM 사용자 매뉴얼 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 사용자 매뉴얼 R2. 차트 지표 레퍼런스 — 메트릭별 의미·문제 신호·임계치
  • OPENMARU APM 사용자 매뉴얼 E3. 지표의 의미 — APDEX · 응답시간 · 처리량 개념
  • OPENMARU APM 사용자 매뉴얼 H3. 나의 대시보드 — 콘솔 안에서 차트를 모아 보기 (PromQL 불필요)
  • OPENMARU APM 사용자 매뉴얼 H18. 사용자·그룹·권한 관리 — API 접근 키 발급 위치