- 什麼是 PromQL
- 資料模型
- 基本查詢
- 選擇器與標籤
- 運算子
- 函式
- 常用查詢範例
- 告警規則
- 效能優化
- 常見問題
- 總結
PromQL(Prometheus Query Language)是 Prometheus 的查詢語言,用於查詢時序資料、建立儀表板和告警規則。
┌─────────────────────────────────────────┐
│ Prometheus │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
Targets ─┼─▶│ Scraper │─▶│ TSDB │◀─│ PromQL │◀─┼─ Grafana
│ └─────────┘ └─────────┘ └─────────┘ │
│ │ │
│ ┌─────▼─────┐ │
│ │Alertmanager│ │
│ └───────────┘ │
└─────────────────────────────────────────┘
| 場景 |
說明 |
| 即時查詢 |
在 Prometheus UI 或 Grafana 查詢當前資料 |
| 儀表板 |
Grafana 圖表的資料來源 |
| 告警規則 |
定義觸發告警的條件 |
| Recording Rules |
預先計算並儲存查詢結果 |
每個時間序列由以下組成:
metric_name{label1="value1", label2="value2"} value timestamp
範例:
http_requests_total{method="GET", status="200"} 1234 1701676800
│ │ │ │
│ │ │ └─ 時間戳記(Unix 毫秒)
│ │ └─ 數值
│ └─ 標籤(Labels)
└─ 指標名稱(Metric Name)
| 類型 |
說明 |
範例 |
| Counter |
只增不減的累計值 |
http_requests_total、errors_total |
| Gauge |
可增可減的瞬時值 |
temperature、memory_usage |
| Histogram |
統計分佈(桶) |
http_request_duration_seconds |
| Summary |
統計分佈(分位數) |
http_request_duration_seconds |
Counter(計數器):
├── 只會增加或重置為 0
├── 適合:請求數、錯誤數、完成的任務數
└── 常用函式:rate(), increase()
Gauge(儀表):
├── 可以任意增減
├── 適合:溫度、記憶體使用量、當前連線數
└── 直接使用或用 delta()
http_request_duration_seconds_bucket{le="0.1"} 1000 # ≤0.1秒 的請求數
http_request_duration_seconds_bucket{le="0.5"} 1500 # ≤0.5秒 的請求數
http_request_duration_seconds_bucket{le="1"} 1800 # ≤1秒 的請求數
http_request_duration_seconds_bucket{le="+Inf"} 2000 # 所有請求數
http_request_duration_seconds_sum 450 # 總耗時
http_request_duration_seconds_count 2000 # 總請求數
查詢某個時間點的所有時間序列。
http_requests_total
http_requests_total{method="GET", status="200"} 1234
http_requests_total{method="GET", status="404"} 56
http_requests_total{method="POST", status="200"} 789
查詢一段時間範圍內的資料。
http_requests_total[5m]
http_requests_total{method="GET"} 1200 @1701676500
http_requests_total{method="GET"} 1210 @1701676560
http_requests_total{method="GET"} 1234 @1701676620
...
| 單位 |
說明 |
s |
秒 |
m |
分鐘 |
h |
小時 |
d |
天 |
w |
週 |
y |
年 |
http_requests_total[30s] # 過去 30 秒
http_requests_total[5m] # 過去 5 分鐘
http_requests_total[1h] # 過去 1 小時
http_requests_total[7d] # 過去 7 天
http_requests_total offset 1h
http_requests_total[5m] offset 1d
http_requests_total @ 1701676800
http_requests_total @ start()
http_requests_total @ end()
| 運算子 |
說明 |
範例 |
= |
完全匹配 |
method="GET" |
!= |
不等於 |
status!="200" |
=~ |
正則匹配 |
method=~"GET|POST" |
!~ |
正則不匹配 |
status!~"5.." |
http_requests_total{method="GET"}
http_requests_total{status!="200"}
http_requests_total{method=~"GET|POST"}
http_requests_total{status=~"5.."}
http_requests_total{method="GET", status="200", job="api-server"}
http_requests_total{status!~"2.."}
| 標籤 |
說明 |
__name__ |
指標名稱 |
job |
抓取任務名稱 |
instance |
抓取目標位址 |
{__name__=~"http_requests_total|http_errors_total"}
{job="api-server"}
| 運算子 |
說明 |
+ |
加法 |
- |
減法 |
* |
乘法 |
/ |
除法 |
% |
取餘數 |
^ |
次方 |
http_errors_total / http_requests_total * 100
node_memory_Active_bytes / node_memory_MemTotal_bytes * 100
node_memory_MemTotal_bytes / 1024 / 1024
| 運算子 |
說明 |
== |
等於 |
!= |
不等於 |
> |
大於 |
< |
小於 |
>= |
大於等於 |
<= |
小於等於 |
node_cpu_usage > 80
http_requests_total > bool 1000
| 運算子 |
說明 |
and |
交集 |
or |
聯集 |
unless |
差集 |
node_cpu_usage > 80 and node_memory_usage > 80
node_cpu_usage > 90 or node_memory_usage > 90
http_requests_total unless http_requests_total{status="200"}
http_errors_total / http_requests_total
http_errors_total / ignoring(status) http_requests_total
http_errors_total / on(method, job) http_requests_total
sum by (job) (http_errors_total) / on(job) group_left sum by (job) (http_requests_total)
計算 Counter 的每秒平均增長率(最常用)。
rate(http_requests_total[5m])
rate(http_errors_total[5m])
計算最後兩個資料點的瞬時增長率(更敏感)。
irate(http_requests_total[5m])
計算時間範圍內的總增長量。
increase(http_requests_total[1h])
increase(http_errors_total[24h])
| 函式 |
用途 |
特點 |
rate() |
平均速率 |
平滑,適合告警 |
irate() |
瞬時速率 |
敏感,適合看趨勢細節 |
increase() |
總增長量 |
適合統計總量 |
sum(http_requests_total)
avg(http_requests_total)
max(node_cpu_usage)
min(node_memory_available)
count(http_requests_total)
stddev(http_request_duration_seconds)
quantile(0.95, http_request_duration_seconds)
topk(5, http_requests_total)
bottomk(5, http_requests_total)
sum by (method) (http_requests_total)
sum by (method, status) (http_requests_total)
sum without (instance) (http_requests_total)
time()
timestamp(http_requests_total)
time() - timestamp(up)
hour()
day_of_week()
abs(temperature)
ceil(value)
floor(value)
round(value, 0.1) # 精確到 0.1
ln(value)
exp(value)
sqrt(value)
label_replace(up, "host", "$1", "instance", "(.*):.*")
label_join(up, "full_name", "-", "job", "instance")
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))
histogram_quantile(0.95, sum by (job, le) (rate(http_request_duration_seconds_bucket[5m])))
absent(up{job="api-server"}) # 如果不存在,回傳 1
clamp(cpu_usage, 0, 100) # 限制在 0-100 之間
clamp_min(value, 0) # 最小值為 0
clamp_max(value, 100) # 最大值為 100
sort(http_requests_total) # 升序
sort_desc(http_requests_total) # 降序
changes(up[1h]) # 過去 1 小時變化了幾次
delta(temperature[1h]) # Gauge 的變化量
deriv(temperature[1h]) # Gauge 的導數(變化速率)
predict_linear(node_filesystem_avail_bytes[1h], 3600 * 24)
100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
sum by (cpu) (irate(node_cpu_seconds_total{mode!="idle"}[5m])) * 100
node_load1 # 1 分鐘負載
node_load5 # 5 分鐘負載
node_load15 # 15 分鐘負載
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100
node_memory_MemAvailable_bytes / 1024 / 1024 / 1024
(node_memory_SwapTotal_bytes - node_memory_SwapFree_bytes) / node_memory_SwapTotal_bytes * 100
(1 - node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100
node_filesystem_avail_bytes{mountpoint="/"} / 1024 / 1024 / 1024
rate(node_disk_read_bytes_total[5m])
rate(node_disk_written_bytes_total[5m])
predict_linear(node_filesystem_avail_bytes[1h], 3600 * 24 * 7)
rate(node_network_receive_bytes_total[5m])
rate(node_network_transmit_bytes_total[5m])
rate(node_network_receive_bytes_total[5m]) * 8 / 1000 / 1000
rate(node_network_receive_errs_total[5m])
rate(node_network_transmit_errs_total[5m])
sum(rate(http_requests_total[5m]))
sum by (status) (rate(http_requests_total[5m]))
sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) * 100
histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))
histogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))
rate(http_request_duration_seconds_sum[5m]) / rate(http_request_duration_seconds_count[5m])
sum by (container) (rate(container_cpu_usage_seconds_total[5m])) * 100
container_memory_usage_bytes{container!=""}
container_memory_usage_bytes / container_spec_memory_limit_bytes * 100
rate(container_network_receive_bytes_total[5m])
rate(container_network_transmit_bytes_total[5m])
sum by (pod) (kube_pod_container_status_restarts_total)
sum by (pod) (increase(kube_pod_container_status_restarts_total[1h]))
kube_pod_status_phase{phase="Running"}
kube_node_status_condition{condition="Ready", status="true"}
kube_deployment_status_replicas_available
kube_horizontalpodautoscaler_status_current_replicas
kube_horizontalpodautoscaler_status_desired_replicas
groups:
- name: example-alerts
rules:
- alert: HighCPUUsage
expr: 100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 5m
labels:
severity: warning
annotations:
summary: "CPU 使用率過高"
description: "實例 {{ $labels.instance }} CPU 使用率 {{ $value | printf \"%.2f\" }}%"
groups:
- name: node-alerts
rules:
- alert: InstanceDown
expr: up == 0
for: 1m
labels:
severity: critical
annotations:
summary: "實例 {{ $labels.instance }} 宕機"
- alert: HighCPUUsage
expr: 100 - (avg by (instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 5m
labels:
severity: warning
annotations:
summary: "CPU 使用率 {{ $value | printf \"%.2f\" }}%"
- alert: LowMemory
expr: (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 > 90
for: 5m
labels:
severity: warning
annotations:
summary: "記憶體使用率 {{ $value | printf \"%.2f\" }}%"
- alert: LowDiskSpace
expr: (1 - node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100 > 85
for: 5m
labels:
severity: warning
annotations:
summary: "磁碟使用率 {{ $value | printf \"%.2f\" }}%"
- alert: DiskWillFillIn24Hours
expr: predict_linear(node_filesystem_avail_bytes[1h], 3600 * 24) < 0
for: 1h
labels:
severity: warning
annotations:
summary: "磁碟預計 24 小時內將滿"
- name: http-alerts
rules:
- alert: HighErrorRate
expr: sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) * 100 > 5
for: 5m
labels:
severity: critical
annotations:
summary: "錯誤率 {{ $value | printf \"%.2f\" }}%"
- alert: HighLatency
expr: histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m]))) > 1
for: 5m
labels:
severity: warning
annotations:
summary: "P95 延遲 {{ $value | printf \"%.2f\" }} 秒"
| 建議 |
說明 |
| 使用標籤過濾 |
先過濾再聚合,減少計算量 |
| 避免過長時間範圍 |
[5m] 比 [1h] 效率高 |
| 使用 Recording Rules |
預先計算常用查詢 |
| 避免高基數標籤 |
如 user_id、request_id |
使用 without 而非 by |
當要排除的標籤較少時 |
預先計算並儲存查詢結果,提升效能。
groups:
- name: recording-rules
rules:
- record: job:http_requests:rate5m
expr: sum by (job) (rate(http_requests_total[5m]))
- record: job:http_error_rate:rate5m
expr: sum by (job) (rate(http_requests_total{status=~"5.."}[5m])) / sum by (job) (rate(http_requests_total[5m]))
- record: job:http_latency_p95:rate5m
expr: histogram_quantile(0.95, sum by (job, le) (rate(http_request_duration_seconds_bucket[5m])))
sum(rate(http_requests_total[5m]))
sum(rate(http_requests_total{job="api-server"}[5m]))
rate(http_requests_total[24h])
rate(http_requests_total[5m])
http_requests_total{user_id="..."}
原因:時間範圍內資料點不足(至少需要 2 個點)
解決:
1. 增加時間範圍(如 [5m] → [10m])
2. 檢查 scrape_interval 設定
3. 時間範圍應至少是 scrape_interval 的 4 倍
resets(http_requests_total[1h])
http_errors_total{method="GET"} / http_requests_total
http_errors_total / ignoring(status) http_requests_total
http_errors_total / on(method) http_requests_total
sum by (method) (http_errors_total) / sum by (method) (http_requests_total)
原因:分位數是估算值,精度取決於 bucket 定義
解決:
1. 調整 bucket 邊界,讓它們更接近實際分佈
2. bucket 越多越準確(但儲存成本越高)
3. 對於精確需求,考慮使用 Summary
| 函式 |
用途 |
範例 |
rate() |
Counter 每秒速率 |
rate(requests[5m]) |
irate() |
瞬時速率 |
irate(requests[5m]) |
increase() |
總增長量 |
increase(requests[1h]) |
sum() |
求和 |
sum by (job) (requests) |
avg() |
平均 |
avg(cpu_usage) |
max() / min() |
最大/最小 |
max(memory) |
topk() |
前 N 名 |
topk(5, requests) |
histogram_quantile() |
分位數 |
histogram_quantile(0.95, ...) |
predict_linear() |
線性預測 |
predict_linear(disk[1h], 86400) |
absent() |
檢查是否缺失 |
absent(up{job="x"}) |
| 需求 |
查詢 |
| QPS |
sum(rate(http_requests_total[5m])) |
| 錯誤率 |
sum(rate(errors[5m])) / sum(rate(requests[5m])) * 100 |
| P95 延遲 |
histogram_quantile(0.95, sum by (le) (rate(duration_bucket[5m]))) |
| CPU 使用率 |
100 - avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100 |
| 記憶體使用率 |
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 |
| 磁碟使用率 |
(1 - node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100 |
| 場景 |
建議範圍 |
| 即時監控 |
[1m] ~ [5m] |
| 告警規則 |
[5m] ~ [15m] |
| 趨勢分析 |
[1h] ~ [24h] |
| 容量規劃 |
[7d] ~ [30d] |
建立日期:2025-12-04
最後更新:2025-12-04