PromQL 서버 자원 사용량 쿼리 시각화 node_exporter 가 노출한 메트릭이 → PromQL 변환을 거쳐 → 차트가 되기까지 (Padion Frontend)

서버
node_exporter
/metrics 노출
Prometheus
주기적 scrape
시계열 저장
PromQL
query_range
로 가공 질의
변환
prometheusTo
UPlotSeries()
uPlot 차트
서버별 선
그래프
핵심 두 타입.   Counter = 계속 누적 증가 → 그대로는 의미없고 rate()로 "초당 증가율"을 구해야 함.   Gauge = 그 순간의 값 → 그대로 사용.

① CPU 사용률 — Counter라서 rate()로 idle을 구해 뒤집는다

CPU Usage (%) COUNTER
100 - avg by (instance) ( rate(node_cpu_seconds_total{mode="idle"}[1m]) ) * 100
1
node_cpu_seconds_total{mode="idle"}
코어별 idle 누적 초 (counter)
core0: 89,412s
core1: 90,105s · · ·
2
rate( … [1m] )
최근 1분 초당 증가율
= "1초 중 몇 초 놀았나" (0~1)
core0: 0.82
core1: 0.90
3
avg by (instance)
서버별 코어 평균
(서버 하나 = 선 하나)
srv1: 0.86
4
* 100 → idle %
비율 → 퍼센트
srv1: 86% idle
5
100 - (…)
뒤집어 사용률
srv1: 14% 사용
{instance="srv1"}
{instance="srv2"}
y축 = 사용률 %, x축 = 시간

② 메모리 사용률 — Gauge라서 rate() 없이 비율 직접 계산

Memory Usage (%) GAUGE
( 1 - ( node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes ) ) * 100
1
MemAvailable / MemTotal
현재값 두 개 (gauge)
여유 비율
6.4GB / 16GB = 0.40
2
1 - (…)
뒤집어 사용 비율
1 - 0.40 = 0.60
3
* 100
퍼센트
60% 사용
왜 rate()가 없나? MemAvailable·MemTotal은 "지금 이 순간의 바이트"인 Gauge라 그 자체로 의미가 있습니다. 반대로 CPU·Network는 "누적 합계"인 Counter라 반드시 rate()가 필요합니다.

③ 네트워크 — Counter rate() 후 단위 환산(B/s → Mbps), 차트 2개

Network TX / RX (Mbps) COUNTER
TX: rate(node_network_transmit_bytes_total[1m]) * 8 / 1024 / 1024 RX: rate(node_network_receive_bytes_total[1m]) * 8 / 1024 / 1024
1
…_bytes_total
누적 전송 바이트 (counter)
9,812,400,128 B
2
rate( … [1m] )
초당 바이트 (B/s)
1,310,720 B/s
3
* 8
바이트 → 비트
10,485,760 b/s
4
/ 1024 / 1024
Mbps
10 Mbps
네트워크만 query 배열에 항목이 2개(TX, RX)라서 Promise.all로 병렬 호출되고 차트 2개가 그려집니다. CPU·Memory는 1개.

④ GPU — 이 프로젝트엔 미구현 (참고)

GPU Usage 미구현
PROMETHEUS_QUERY.gpu = [] // 드롭다운엔 있지만 쿼리가 빈 배열 → 차트 안 그려짐
GPU는 node_exporter가 주지 않습니다. NVIDIA DCGM exporter를 따로 설치하면 아래처럼 쿼리할 수 있습니다 (대부분 Gauge라 rate 불필요):
DCGM_FI_DEV_GPU_UTIL // GPU 사용률 % (gauge) DCGM_FI_DEV_FB_USED / (DCGM_FI_DEV_FB_USED + DCGM_FI_DEV_FB_FREE) * 100 // GPU 메모리 %
※ 프로젝트의 hostGpuCnt/hostGpuMemSize는 Prometheus 메트릭이 아니라 호스트 등록 폼의 수동 입력값입니다.

한눈 요약

리소스메트릭 타입rate() 필요?핵심 변환차트 수
CPUCounter✅ 필요idle율 구해 100-로 뒤집기1
MemoryGauge❌ 불필요(1 - 여유/전체) × 1001
NetworkCounter✅ 필요B/s → ×8 → Mbps 환산2 (TX·RX)
GPU(DCGM)대개 ❌미구현 — DCGM exporter 필요0
서버 선택은 어디에? 위 모든 쿼리의 메트릭 뒤에 injectNameMatcher()name="srv1"(1개) 또는 name=~"srv1|srv2"(여러 개)를 동적으로 끼워넣습니다. 그래서 응답이 서버별로 갈라지고 → 차트에 서버마다 선 하나로 그려집니다.
Padion Frontend · constants/prometheus.ts + util/prometheus.ts 기반 · 값은 설명용 예시