Links#
https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/
https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/
https://prometheus.io/docs/prometheus/latest/querying/basics/
https://prometheus.io/docs/prometheus/latest/querying/operators/
https://prometheus.io/docs/prometheus/latest/querying/functions/
https://docs.victoriametrics.com/victoriametrics/vmalert/
https://github.com/google/re2/wiki/Syntax1. Rule File Structure#
当前 rule 文件是 Prometheus/vmalert 兼容格式。文件顶层是 groups,每个 group 里放一组 recording rules 或 alerting rules;interval 是这个 group 多久评估一次,expr 是 PromQL/MetricsQL 表达式。
groups:
- name: aws-alb.recording.rules
interval: 1m
rules:
- record: aws:alb:request_count:sum5m
expr: |
sum by (environment, dimension_LoadBalancer) (
sum_over_time(aws_applicationelb_request_count_sum[5m])
)
- name: aws-alb.alerting.rules
interval: 1m
rules:
- alert: AwsAlbElb5xxRateHigh
expr: aws:alb:elb_5xx_rate:ratio5m > 0.01
for: 5m
labels:
severity: P1
service: alb
annotations:
summary: "ALB 5xx rate is high"| Key | Meaning |
|---|---|
groups |
rule group list |
name |
group name, file 内唯一即可 |
interval |
evaluation interval,例如 1m |
rules |
当前 group 下的 rule list |
record |
recording rule,计算结果会写成一个新 metric |
alert |
alerting rule,表达式返回的每条 series 都会变成一条 alert |
expr |
PromQL/MetricsQL 表达式 |
for |
条件持续多久才 firing;之前是 pending |
labels |
alert 静态标签,用于 routing/grouping,例如 severity/team/service |
annotations |
给人看的上下文,例如 summary、dashboard、runbook |
| `expr: | ` |
interval 和 for 的关系:
recording group:
interval: 1m
每 1 分钟执行一次 recording rule
每次把 expr 的结果写成 record 指定的新 metric
alerting group:
interval: 1m
每 1 分钟执行一次 alerting rule 的 expr
for: 5m:
不是 5 分钟里有一次满足就 firing
而是这条 alert series 必须连续保持 true 满 5 分钟
在 firing 之前状态是 pending
中间任何一次 evaluation 变成 false,这个 pending 计时会重置Example timeline:
interval = 1m
for = 5m
00:00 expr=true alert enters pending
00:01 expr=true pending 1m
00:02 expr=true pending 2m
00:03 expr=true pending 3m
00:04 expr=true pending 4m
00:05 expr=true firing
if one evaluation becomes false:
00:00 expr=true alert enters pending
00:01 expr=true pending 1m
00:02 expr=false pending reset, alert inactive
00:03 expr=true pending starts again
00:04 expr=true pending 1m
00:05 expr=true pending 2m所以 interval: 1m + for: 5m 可以理解成每 1 分钟检查一次,表达式需要连续约 5 分钟都满足。实际 firing 时间会受 evaluation 时间点、数据延迟、rule reload 影响,不要理解成“固定恰好检查 5 次”。
如果希望某次 evaluation 只要满足就立即触发,不要把 for 写成 interval 的时间,而是不要写 for,或者显式写 for: 0m。
Immediate firing sample:
groups:
- name: api.alerting.rules
interval: 1m
rules:
- alert: ApiDown
expr: up{job="order-api"} == 0
labels:
severity: P1
service: order-apiTimeline:
interval = 1m
for is not set
00:00 expr=false inactive
00:01 expr=true firing immediately
00:02 expr=true still firing
00:03 expr=false resolved对比 for: 1m:
interval = 1m
for = 1m
00:00 expr=true alert enters pending
00:01 expr=true firing所以 for: 1m 不是“出现一次就触发”,而是至少要持续到下一次 evaluation 仍然满足。P1 需要立即触发时可以不写 for,但建议表达式本身带 traffic guard 或多条件判断,避免单点毛刺。
2. Reading An Expression#
先按这个顺序读:metric selector -> range/function -> aggregation -> arithmetic -> comparison -> vector matching。
aws:alb_targetgroup:target_5xx_rate:ratio5m > 0.05
and on (environment, dimension_LoadBalancer, dimension_TargetGroup)
aws:alb_targetgroup:request_count:sum5m >= 100
and on (environment, dimension_LoadBalancer, dimension_TargetGroup)
aws:alb_targetgroup:target_5xx_count:sum5m >= 10意思是:同一个 environment + LoadBalancer + TargetGroup 上,5xx 比例大于 5%,并且 5 分钟请求数至少 100,并且 5xx 次数至少 10。后两个条件是 traffic guard,避免低流量下 1 个错误就触发高比例告警。
3. Metric Selector#
最基础的 selector 是 metric_name{label matcher}。AWS/YACE 的 CloudWatch 维度通常会变成 dimension_xxx label,例如 dimension_TableName、dimension_Operation、dimension_LoadBalancer。
aws_dynamodb_successful_request_latency_p95{
dimension_TableName!="",
dimension_Operation=~"GetItem|PutItem|UpdateItem|DeleteItem"
}Sample input:
aws_dynamodb_successful_request_latency_p95{environment="prod", dimension_TableName="orders", dimension_Operation="GetItem"} 0.012
aws_dynamodb_successful_request_latency_p95{environment="prod", dimension_TableName="orders", dimension_Operation="PutItem"} 0.031
aws_dynamodb_successful_request_latency_p95{environment="prod", dimension_TableName="orders", dimension_Operation="Scan"} 0.180
aws_dynamodb_successful_request_latency_p95{environment="prod", dimension_TableName="", dimension_Operation="GetItem"} 0.009
aws_dynamodb_successful_request_latency_p95{environment="prod", dimension_TableName="users", dimension_Operation="UpdateItem"} 0.044
aws_dynamodb_successful_request_latency_p95{environment="prod", dimension_TableName="users", dimension_Operation="BatchGetItem"} 0.070After selector:
aws_dynamodb_successful_request_latency_p95{environment="prod", dimension_TableName="orders", dimension_Operation="GetItem"} 0.012
aws_dynamodb_successful_request_latency_p95{environment="prod", dimension_TableName="orders", dimension_Operation="PutItem"} 0.031
aws_dynamodb_successful_request_latency_p95{environment="prod", dimension_TableName="users", dimension_Operation="UpdateItem"} 0.044被过滤掉的 series:
dimension_Operation="Scan":
不匹配 GetItem|PutItem|UpdateItem|DeleteItem
dimension_TableName="":
被 dimension_TableName!="" 排除
dimension_Operation="BatchGetItem":
不在 regex 列表里| Matcher | Meaning |
|---|---|
label="value" |
label 精确等于 value |
label!="value" |
label 不等于 value |
label=~"regex" |
label 匹配 RE2 regex |
label!~"regex" |
label 不匹配 RE2 regex |
dimension_TableName!="" |
只保留 table name 非空的 series,常用于排除无维度聚合数据 |
注意:Prometheus label regex matcher 是 fully anchored,job=~"node" 只匹配完整值 node;要包含匹配要写 job=~".*node.*"。label="" 会匹配空值,也可能匹配没有这个 label 的 series,所以排除缺失/空值常用 label!=""。
4. Range Vector And Duration#
[5m] 把 instant vector 变成 range vector,意思是“每条 series 最近 5 分钟内实际存在的样本”。sum_over_time(metric[5m])、rate(counter[5m]) 这类函数需要 range vector。
| Syntax | Meaning |
|---|---|
metric |
instant vector,当前评估时间点的值 |
metric[5m] |
range vector,最近 5 分钟内实际采集到的样本 |
for: 10m |
表达式连续 10 分钟为 true 才 firing |
interval: 1m |
每 1 分钟评估一次 rule |
[5m] 不是固定取 5 个点,而是按时间窗口取样本。采集间隔是 1 分钟时,通常能看到约 5 个样本;采集间隔是 3 分钟时,5 分钟窗口里可能只有 1 到 2 个样本。
metric_name{label="value"}:
metric name + labels 选中一条或多条 time series
metric_name{label="value"}[5m]:
每条 series 最近 5 分钟内的 samples
sum_over_time(metric_name{label="value"}[5m]):
对每条 series 自己的 5 分钟 samples 求和常见 duration:30s、1m、5m、10m、1h。CloudWatch/YACE 很多指标 5 分钟一个点,for 不要太短,否则容易受采集延迟影响。
5. Aggregation#
Aggregation 用来把多条 series 合并成更有业务意义的粒度。by (...) 指定哪些 label 被保留;没写在 by 里的 label 会被聚合掉。
sum by (environment, dimension_QueueName) (
sum_over_time(aws_sqs_number_of_messages_deleted_sum{dimension_QueueName!=""}[5m])
)Sample input at current evaluation time:
aws_sqs_number_of_messages_deleted_sum{environment="prod", dimension_QueueName="orders"}[5m]
10 12 8 15 5
aws_sqs_number_of_messages_deleted_sum{environment="prod", dimension_QueueName="payments"}[5m]
3 7 0 9 1
aws_sqs_number_of_messages_deleted_sum{environment="uat", dimension_QueueName="orders"}[5m]
1 2 0 3 4
aws_sqs_number_of_messages_deleted_sum{environment="prod", dimension_QueueName=""}[5m]
100 120 110 90 80这里的 10 12 8 15 5 表示同一条 time series 在最近 5 分钟窗口内采集到的 samples,不是 5 条不同 metric。
metric name:
aws_sqs_number_of_messages_deleted_sum
labels:
environment="prod"
dimension_QueueName="orders"
range:
[5m] 表示当前评估时间往前 5 分钟
samples:
10 12 8 15 5
如果采集间隔是 1m,可以理解成 5 个 1m period 的值
如果采集间隔是 3m,5m 窗口里可能只有 1 到 2 个值对 CloudWatch/YACE 的 *_sum 计数类 metric 来说,每个 sample 通常是一个 CloudWatch period 内的 Sum 值。所以上面的例子可以理解为:orders 队列最近 5 个 period 分别删除了 10 / 12 / 8 / 15 / 5 条消息。
Selector first:
aws_sqs_number_of_messages_deleted_sum{dimension_QueueName!=""}[5m]After selector:
aws_sqs_number_of_messages_deleted_sum{environment="prod", dimension_QueueName="orders"}[5m]
10 12 8 15 5
aws_sqs_number_of_messages_deleted_sum{environment="prod", dimension_QueueName="payments"}[5m]
3 7 0 9 1
aws_sqs_number_of_messages_deleted_sum{environment="uat", dimension_QueueName="orders"}[5m]
1 2 0 3 4Then sum_over_time(...):
sum_over_time(aws_sqs_number_of_messages_deleted_sum{dimension_QueueName!=""}[5m])Result:
{environment="prod", dimension_QueueName="orders"} 50
{environment="prod", dimension_QueueName="payments"} 20
{environment="uat", dimension_QueueName="orders"} 10Then sum by (environment, dimension_QueueName) (...):
{environment="prod", dimension_QueueName="orders"} 50
{environment="prod", dimension_QueueName="payments"} 20
{environment="uat", dimension_QueueName="orders"} 10这个例子里每个 queue 只有一条 series,所以 sum by 后数值没有变化。真实数据里如果还带有 job、instance、account_id、region 等 label,sum by (environment, dimension_QueueName) 会把这些 label 聚合掉,只保留每个环境下每个 queue 的总数。
With extra labels:
after sum_over_time:
{environment="prod", dimension_QueueName="orders", instance="yace-1"} 30
{environment="prod", dimension_QueueName="orders", instance="yace-2"} 20
after sum by (environment, dimension_QueueName):
{environment="prod", dimension_QueueName="orders"} 50| Function | When To Use |
|---|---|
sum by (...) |
count/request/error/backlog 总量,例如 5xx count、SQS messages |
avg by (...) |
utilization/latency statistic 的普通视图,例如 CPU%、memory%、p95 metric 已经由 CloudWatch 算好 |
max by (...) |
关注最坏实例/最大延迟/最大 lag,例如 replica lag |
min by (...) |
关注最小健康容量,例如 ALB healthy host count 要看最小值是否跌到 0 |
保留 label 的原则:保留能定位 owner 和资源的 label,例如 environment、dimension_TableName、dimension_QueueName、instance;不要保留高基数且排障价值低的 label。
6. Functions Used Here#
当前 rule 主要用这些函数。
| Function | Input | Meaning | Example |
|---|---|---|---|
sum_over_time(x[5m]) |
range vector | 最近 5 分钟所有样本求和 | CloudWatch *_sum 计数类指标 |
rate(counter[5m]) |
counter range vector | counter 每秒速率,自动处理 reset | node CPU、disk IO counter |
clamp_min(x, 1) |
instant vector | 把小于 1 的值抬到 1,避免除 0 | error_count / clamp_min(request_count, 1) |
CloudWatch/YACE 计数类 metric 名里常见 *_sum,它不是 Prometheus counter,而是 CloudWatch period 内的 Sum 统计值,所以常用 sum_over_time(metric_sum[5m]) 得到窗口内总数。node exporter 的 node_cpu_seconds_total 是 Prometheus counter,所以用 rate(...[5m])。
rate(counter[5m]) 用来把持续递增的 counter 转成“每秒速率”。counter 的原始值是累计总数,不是每分钟的新增数。
Sample counter:
scrape_interval = 10s:
5 分钟窗口里大约 31 个点
300s / 10s + 1 = 31
http_requests_total{service="order-api", status="200"}[5m]
t+000s 1000
t+010s 1010
t+020s 1020
t+030s 1030
t+040s 1040
t+050s 1050
t+060s 1060
t+070s 1070
t+080s 1080
t+090s 1090
t+100s 1100
t+110s 1110
t+120s 1120
t+130s 1130
t+140s 1140
t+150s 1150
t+160s 1160
t+170s 1170
t+180s 1180
t+190s 1190
t+200s 1200
t+210s 1210
t+220s 1220
t+230s 1230
t+240s 1240
t+250s 1250
t+260s 1260
t+270s 1270
t+280s 1280
t+290s 1290
t+300s 1300Meaning:
1000:
进程启动以来累计处理了 1000 个请求
1300:
5 分钟后累计处理了 1300 个请求
increase over 5m:
1300 - 1000 = 300 requests
rate over 5m:
300 / 300s = 1 request/secondQuery:
rate(http_requests_total{service="order-api", status="200"}[5m])Result:
{service="order-api", status="200"} 1如果想要“最近 5 分钟总共多少请求”,用 increase 更直观:
increase(http_requests_total{service="order-api", status="200"}[5m])Result:
{service="order-api", status="200"} 300Counter reset:
http_requests_total{service="order-api"}[5m]
1000 1060 1120 20 80 140这里进程重启后 counter 从 1120 变成 20。rate / increase 会处理这种 reset,不会直接用 140 - 1000 得到负数。
Same samples with different functions:
input:
scrape_interval = 10s
http_requests_total{service="order-api", status="200"}[5m]
t+000s 1000
t+010s 1010
t+020s 1020
t+030s 1030
t+040s 1040
t+050s 1050
t+060s 1060
t+070s 1070
t+080s 1080
t+090s 1090
t+100s 1100
t+110s 1110
t+120s 1120
t+130s 1130
t+140s 1140
t+150s 1150
t+160s 1160
t+170s 1170
t+180s 1180
t+190s 1190
t+200s 1200
t+210s 1210
t+220s 1220
t+230s 1230
t+240s 1240
t+250s 1250
t+260s 1260
t+270s 1270
t+280s 1280
t+290s 1290
t+300s 1300
http_requests_total{service="order-api", status="200"}:
1300
当前评估时间点的最新累计值
http_requests_total{service="order-api", status="200"}[5m]:
1000 1010 1020 1030 1040 1050 1060 1070 1080 1090
1100 1110 1120 1130 1140 1150 1160 1170 1180 1190
1200 1210 1220 1230 1240 1250 1260 1270 1280 1290 1300
最近 5 分钟窗口内这条 series 的 samples
rate(http_requests_total{service="order-api", status="200"}[5m]):
(1300 - 1000) / 300s = 1 request/second
适合告警和 dashboard 展示 QPS / RPS
increase(http_requests_total{service="order-api", status="200"}[5m]):
1300 - 1000 = 300 requests
适合展示最近 5 分钟总请求数
sum_over_time example, using CloudWatch/YACE period sum metric:
aws_sqs_number_of_messages_deleted_sum{dimension_QueueName="orders"}[5m]
10 12 8 15 5
sum_over_time(...[5m])
10 + 12 + 8 + 15 + 5 = 50
meaning:
orders queue 最近 5 个 period 一共删除了 50 条消息
avg_over_time example, using gauge:
node_memory_used_percent{instance="node-1"}[5m]
70 72 75 73 80
avg_over_time(...[5m])
(70 + 72 + 75 + 73 + 80) / 5 = 74
meaning:
node-1 最近 5 分钟平均内存使用率是 74%
max_over_time example, using gauge / statistic value:
http_request_duration_seconds_p95{service="order-api"}[5m]
0.20 0.35 0.80 0.40 0.30
max_over_time(...[5m])
max(0.20, 0.35, 0.80, 0.40, 0.30) = 0.80
meaning:
order-api 最近 5 分钟内最差的 p95 延迟是 0.80s结论:
counter:
用 rate 看每秒速率
用 increase 看窗口内增长总量
不要用 sum_over_time 计算请求数
gauge:
用 avg_over_time / max_over_time / min_over_time 看窗口内统计值容易混淆:
range selector:
[5m] 是时间窗口,不是固定 5 个点
点数由 scrape interval / CloudWatch period / 采集延迟决定
sum_over_time:
对同一条 series 在时间窗口内的 samples 求和
适合 CloudWatch/YACE 的 *_sum 计数类 period value
不适合 CPU utilization / latency p95 这类 gauge 或统计值直接求和
sum by:
对同一时间点的多条 series 做 label 维度聚合
例如把 instance / job / region 聚合掉,只保留 queue 或 table 维度
counter:
Prometheus 原生 counter 通常用 rate(counter[5m]) 或 increase(counter[5m])
不要用 sum_over_time(counter[5m]) 计算请求数
gauge:
CPU / memory / latency p95 这类值通常用 avg_over_time / max_over_time
不要看到 [5m] 就默认套 sum_over_time7. Arithmetic And Comparison#
表达式可以做四则运算和比较。比较结果仍然是 vector:每条满足条件的 series 被保留,不满足的被丢掉。
aws:alb:elb_5xx_count:sum5m / clamp_min(aws:alb:request_count:sum5m, 1)
aws:rds_cluster:cpu_utilization:avg > 85
node:memory_used_percent > 90| Operator | Meaning |
|---|---|
+ - * / |
数学运算 |
> < >= <= == != |
比较;告警通常用这些产生 firing series |
0.05 |
ratio 5%;如果表达式是 percent,则写 5 |
100 * x |
把 ratio 转成 percent |
写 rule 前先确认单位:ALB error rate 如果 recording rule 名是 ratio5m,阈值 5% 写 0.05;CPU utilization 是 percent,阈值 85% 写 85;latency 有些 AWS metric 单位是 seconds,有些 dashboard 显示成 ms,必须看原始 metric 单位。
8. Vector Matching: and on / or on#
PromQL 里两个 vector 做二元运算时,默认按完全相同的 label set 匹配。实际 rule 经常需要指定“只按这些 label 匹配”,这就是 on (...)。
aws:ecs_service:task_deficit:avg > 0
and on (environment, dimension_ClusterName, dimension_ServiceName)
aws:ecs_service:desired_task_count:avg > 0意思是:左边找出 task deficit 大于 0 的 service;右边只保留 desired task 大于 0 的 service;and on (...) 表示只有左右两边在这些 label 上能匹配时,才保留左边那条 series。这个写法可以避免 desired=0 的停用服务误报。
三个条件就继续链式写:
A
and on (environment, dimension_QueueName) B
and on (environment, dimension_QueueName) Cor on (...) 常用于补 0 或保留另一侧 series。例如 ALB target 5xx count 缺失时,可以用 request_count 乘 0 补出同 label 的 0 值,避免除法结果缺 series。
(
aws:alb_targetgroup:target_5xx_count:sum5m
or on (environment, dimension_LoadBalancer, dimension_TargetGroup)
0 * aws:alb_targetgroup:request_count:sum5m
)
/ clamp_min(aws:alb_targetgroup:request_count:sum5m, 1)9. Regex Used In These Rules#
Prometheus 使用 RE2 regex,不支持 lookahead/lookbehind/backreference。常用写法如下。
| Regex | Meaning |
|---|---|
| `GetItem | PutItem |
.*node.* |
包含 node |
| `/boot($ | /.*)` |
| `/boot($ | /.*) |
| `tmpfs | devtmpfs |
Regex 在 YAML 双引号里要注意反斜杠转义。当前规则里大部分 regex 没有 \d 这类转义,所以直接写即可;如果需要匹配字面点号,写 "api\\.example\\.com"。
10. Recording Rule Naming#
Recording rule 是给复杂表达式取一个稳定 metric 名,方便 dashboard 和 alert 复用。命名建议读起来像“资源:指标:统计窗口/统计方式”。
aws:alb:request_count:sum5m
aws:alb_targetgroup:target_5xx_rate:ratio5m
aws:rds_cluster:aurora_replica_lag:max
node:cpu_used_percent:avg5m常用 suffix:sum5m 表示窗口总数;rate5m 表示 5 分钟速率;avg/max/min/p95 表示统计方式;ratio 表示 0 到 1 的比例;percent 表示 0 到 100 的百分比。
11. Alert Rule Design#
一个好的 alert expression 通常包含 symptom、scope、threshold、duration、noise guard。
- alert: AwsCloudFront5xxErrorRateHigh
expr: |
aws:cloudfront_distribution:5xx_error_rate:avg > 1
and on (environment, dimension_DistributionId)
aws:cloudfront_distribution:requests:sum5m >= 1000
for: 5m
labels:
severity: P1
service: cloudfront
annotations:
summary: "CloudFront 5xx error rate is high"| Part | Example | Why |
|---|---|---|
| symptom | 5xx_error_rate > 1 |
真正影响用户或系统健康的现象 |
| scope | by (environment, dimension_DistributionId) |
告警能定位资源 |
| threshold | > 1 |
与单位一致,1 表示 1% 而不是 0.01 |
| duration | for: 5m |
避免单点毛刺 |
| guard | requests >= 1000 |
低流量时避免比例误报 |
12. AWS/YACE Metric Patterns#
YACE 会把 CloudWatch metric 和 dimension 展开成 Prometheus label。写 rule 时要先确认 dashboard 或 Explore 里的真实 label,不要凭 AWS 控制台名字猜。
| AWS Dimension | YACE Label Example |
|---|---|
| LoadBalancer | dimension_LoadBalancer |
| TargetGroup | dimension_TargetGroup |
| ClusterName | dimension_ClusterName |
| ServiceName | dimension_ServiceName |
| DBClusterIdentifier | dimension_DBClusterIdentifier |
| CacheClusterId | dimension_CacheClusterId |
| QueueName | dimension_QueueName |
| TableName | dimension_TableName |
| Operation | dimension_Operation |
| DistributionId | dimension_DistributionId |
CloudWatch statistic 也要看清楚:_sum 常用于计数窗口求和;_average 用于平均利用率;_maximum 用于最坏值,例如最大 lag;_minimum 用于最小健康容量,例如 healthy host count 是否跌到 0。
13. Host Rule Patterns#
node exporter rule 和 AWS CloudWatch rule 不一样,它基于操作系统 counter/gauge。
100 - (
avg by (environment, instance) (
rate(node_cpu_seconds_total{mode="idle"}[5m])
) * 100
)这个 CPU 表达式表示:idle CPU 每秒速率的平均值乘 100 得到 idle percent,再用 100 - idle 得到 used percent。
100 * (
1 - (
node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes
)
)这个 memory 表达式表示:可用内存占总内存比例越低,已使用比例越高。disk rule 需要排除 pseudo filesystem 和临时 mountpoint,否则会有大量无意义告警。
14. Write A New Rule#
写新 rule 可以按这个模板走。
1. 在 Grafana Explore 找到真实 metric name 和 labels。
2. 判断 metric 类型:CloudWatch sum / CloudWatch average / Prometheus counter / gauge。
3. 决定告警粒度:ALB、target group、queue、table、instance。
4. 用 recording rule 固化复杂表达式,并保留定位资源需要的 labels。
5. alert rule 只写清楚 threshold、traffic guard、for、labels、annotations。
6. 检查单位:ratio/percent、seconds/milliseconds、bytes/GB、count/rate。
7. 用 promtool 或 vmalert API 检查 rule 是否加载和评估成功。最小模板:
groups:
- name: example.recording.rules
interval: 1m
rules:
- record: resource:metric:stat
expr: |
sum by (environment, resource_label) (
sum_over_time(raw_metric_sum{resource_label!=""}[5m])
)
- name: example.alerting.rules
interval: 1m
rules:
- alert: ResourceMetricHigh
expr: |
resource:metric:stat > THRESHOLD
for: 5m
labels:
severity: P1
service: service-name
annotations:
summary: "Resource metric is high"15. Common Mistakes#
| Mistake | Correct Approach |
|---|---|
把 ratio 当 percent |
0.05 是 5%;5 是 500% |
| 把 percent 当 ratio | CloudFront 5xxErrorRate 如果单位是 percent,1% 写 1 |
| label 写错 | 先查真实 label,例如 DynamoDB 是 dimension_Operation 不是 operation |
| 聚合后丢定位 label | sum by (...) 里保留 queue/table/instance 等资源 label |
| 低流量比例误报 | error rate rule 加 request count guard |
| 对 counter 用普通差值 | Prometheus counter 用 rate/increase;CloudWatch sum 用 sum_over_time |
for 太短 |
CloudWatch 指标通常考虑采集周期和延迟 |
| regex 以为是 contains | label regex fully anchored,contains 要写 .*xxx.* |
| 用错 average/max/min | 看告警语义:平均趋势用 average,最坏实例用 max,最小健康容量用 min |
16. Quick Checks#
promtool check rules *.yml
curl -s http://vmalert:8880/api/v1/rules
curl -s http://vmalert:8880/api/v1/alerts如果 lastEvaluation 是 0001-01-01T00:00:00Z,通常表示这个 rule 还没有被当前 vmalert 实例实际评估过,常见原因是文件没被加载、group 被禁用、vmalert 刚启动还没评估、或 API 查到的不是正在运行的 rule group。