如何用Prometheus Query计算用户级响应占区域请求的百分比?
如何用PromQL计算各区域用户响应数占总请求数的百分比?
问题背景
我们有一个处理HTTP请求并返回匹配用户数据的服务,需要在Grafana中可视化两个指标的占比关系:
- 总请求数指标:
application_requests_total,仅带data_center_region_id标签区分数据中心,示例:application_requests_total{data_center_region_id=1} // 200 application_requests_total{data_center_region_id=2} // 100 - 匹配用户响应数指标:
application_response_total,带user和data_center_region_id标签,单个响应包含多个用户数据的情况已在指标中体现,示例:application_response_total{user="user1", data_center_region_id=1} // 100 application_response_total{user="user1", data_center_region_id=2} // 100 application_response_total{user="user2", data_center_region_id=1} // 50 application_response_total{user="user2", data_center_region_id=2} // 100
核心需求
计算每个数据中心区域内,单个用户的响应数占该区域总请求数的百分比,预期结果:
- data_center_region_id=1:
- user1:100/200 = 50%
- user2:50/200 = 25%
- data_center_region_id=2:
- user1:100/100 = 100%
- user2:100/100 = 100%
原查询问题分析
你写的查询有两个关键错误:
- 总请求数指标
application_requests_total没有user标签,用on(user)做匹配完全不成立,两边不存在共同的user标签 - 总请求数的聚合维度错误,总请求数和用户无关,应该只按
data_center_region_id聚合,而非user, data_center_region_id
正确PromQL查询
基础占比计算(小数形式)
sum(rate(application_response_total{data_center_region_id=~"$region"}[5m])) by (user, data_center_region_id) / on(data_center_region_id) group_left(user) sum(rate(application_requests_total{data_center_region_id=~"$region"}[5m])) by (data_center_region_id)
百分比形式(乘以100)
100 * ( sum(rate(application_response_total{data_center_region_id=~"$region"}[5m])) by (user, data_center_region_id) / on(data_center_region_id) group_left(user) sum(rate(application_requests_total{data_center_region_id=~"$region"}[5m])) by (data_center_region_id) )
逻辑说明
- 分子:按
user和data_center_region_id聚合,得到每个区域下每个用户的响应速率总和 - 分母:仅按
data_center_region_id聚合,得到每个区域的总请求速率总和 - 匹配规则:
on(data_center_region_id)指定按区域标签做匹配,group_left(user)表示保留左边(分子)的user标签,让每个区域的总请求数与该区域下所有用户的响应数逐一做除法
其他可视化方式
Grafana多面板联动
- 先做一个显示各区域总请求数的单值/条形图面板
- 再做一个显示各区域分用户响应数的堆叠条形图面板
- 通过Grafana的区域变量实现面板联动,直观对比响应数与总请求数的占比关系
预计算指标(高基数场景推荐)
如果用户基数很大,实时计算占比可能影响Prometheus性能,可以通过Prometheus记录规则预计算占比:groups: - name: user_response_ratio rules: - record: application_user_response_ratio expr: | sum(rate(application_response_total[5m])) by (user, data_center_region_id) / on(data_center_region_id) group_left(user) sum(rate(application_requests_total[5m])) by (data_center_region_id)之后直接在Grafana中查询
application_user_response_ratio即可,性能更优
内容的提问来源于stack exchange,提问作者user3067435
相关产品推荐
相关产品推荐

