找出核心业务中,P95 延迟最高的 24 个应用。
sql
topk_max(24,
histogram_quantile(0.95,
sum(rate(hllci_es_request_seconds_bucket{hll_appid!~"bfe-mvc-logconsumer-svc|bfe-hll-mcv-crash-service-svc|ci-trace-api|bfe-edog-center-api"}[1m]))
BY (hll_appid,le)
) * 1000
unless on (hll_appid) (cmdb_appid_critical{is_core="1"}))
hllci_es_request_seconds_bucket{...}: 这是一个直方图指标(_bucket后缀),用于记录 ES (Elasticsearch) 请求的耗时分布。hll_appid标签标识了不同的应用。{hll_appid!~"bfe-mvc...}"}: 一个过滤器,使用正则表达式!~来排除后面列出的四个特定的应用(可能是日志消费者、追踪服务等非核心业务应用)。rate(...[1m]): 计算该直方图指标在过去 1 分钟内的每秒增长率。这对于计数器类型的直方图桶是必要操作,因为它会持续增长。sum(...) BY (hll_appid, le): 将速率计算结果按hll_appid(应用名)和le(直方桶的边界标签)进行分组求和。这一步是为每个应用构建一个完整的延迟分布。histogram_quantile(0.95, ...): 这是关键函数。它根据上一步生成的延迟分布,为每个应用计算其 P95 分位数。即 95% 的请求耗时低于这个值。* 1000: 将最终结果从秒 转换为毫秒 ,因为request_seconds的单位是秒,而毫秒是更常用的延迟单位。cmdb_appid_critical{is_core="1"}: 查询另一个指标,这个指标可能来自 CMDB(配置管理数据库)或服务注册中心。它标记了哪些应用是核心应用(is_core="1")。unless on (hll_appid):unless是集合运算符,意思是"排除"。on (hll_appid)指定了操作所依据的标签。- 操作逻辑 :从左边(核心计算部分的结果)的序列中,排除掉 那些其
hll_appid标签值出现在右边(cmdb_appid_critical结果)的序列。 opk_max(24, ...): 这是一个聚合运算符。它会从内部查询结果中,根据每个时间序列的样本值(即延迟数值),选出数值最大的 24 个。_max后缀表示它使用每个时间序列在查询时间范围内的最大值来进行排序和选择。
按 dalGroup 分组,检测在过去一段时间内,是否有任何应用组发生了数据库连接故障(无可用主库)。
sql
sum(
topk(50, increase(heartbeat_no_available_master{hll_appid!="ci-dal-regression-test"}[$__interval]))
) BY (dalGroup) > 0
heartbeat_no_available_master:这是一个计数器。它的名称表明,它用于记录"无可用主库"的心跳事件。每当一个应用实例检测到其数据库主库不可用时,这个计数器就会增加。{hll_appid!="ci-dal-regression-test"}:一个过滤器,排除掉hll_appid为"ci-dal-regression-test"的应用。这通常是一个测试环境的应用,排除它是为了避免测试噪声干扰生产监控。[$__interval]:这是一个在 Grafana 中常用的变量。$__interval会自动被 Grafana 替换为当前图表时间范围内合适的查询步长(例如,查看过去1小时可能为1m,查看过去7天可能为1h)。increase(...[$__interval])计算的就是在这个动态时间窗口内,该计数器增加的绝对数量 。- 结果 :这部分查询会返回一个区间向量 ,表示在
$__interval时间内,每个排除测试应用后的序列(通常由hll_appid,dalGroup等标签标识)所发生的"无可用主库"事件的总次数。
- 结果 :这部分查询会返回一个区间向量 ,表示在
topk(50, ...):这个函数从内层increase(...)的结果中,取出计数器值(即无主库事件发生次数)最高的50个时间序列。sum(...) BY (dalGroup):将topk筛选出的50个最严重的序列,按照dalGroup(数据库组)这个标签进行分组求和。- 这意味着,同一个
dalGroup下的所有应用实例发生的无主库事件次数会被加在一起 。这非常重要,因为它将监控视角从单个应用实例 提升到了数据库资源组的层面。一个数据库主库挂掉,会影响到所有连接它的应用实例。
- 这意味着,同一个
> 0:这是一个布尔判断。它将上面每个dalGroup的求和结果与0进行比较。- 如果结果大于0 :返回
1(表示true) - 如果结果等于0 :返回空集 (表示
false,在Prometheus中不返回数据点)
- 如果结果大于0 :返回
为什么这是一条优秀的告警规则查询?
- 资源维度 :它不是在应用维度告警,而是在数据库资源维度告警。一个主库故障会触发一条告警,而不是成百上千个应用实例各自触发一条告警,避免了告警风暴。
- 避免噪声 :通过
topk(50)和$__interval进行了优化,并排除了测试数据。 - 明确性 :
> 0的条件非常清晰,只要有问题就告警,没有则不告警。