你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
本文提供了在 Azure Monitor 中使用 Prometheus 查询语言(PromQL)查询 OpenTelemetry 指标的最佳做法。 OpenTelemetry 指标具有独特的特征,在编写 PromQL 查询时需要特定注意事项,尤其是围绕字符编码、指标命名和数据时态。
先决条件
- 配置了 OpenTelemetry 指标引入的 Azure Monitor 工作区
- 熟悉 PromQL 基础知识
- 了解 OpenTelemetry 指标约定
- Prometheus 查询基础知识介绍
Prometheus 和 OpenTelemetry 指标之间的主要区别
OpenTelemetry 指标不同于传统的 Prometheus 指标,这些指标以多种重要方式影响编写 PromQL 查询的方式:
指标命名和字符编码
OpenTelemetry 指标通常包含需要 PromQL 中特殊处理的字符:
-
指标名称中的点:OpenTelemetry 在指标名称中使用点(
.),例如http.server.duration。 - 标签中的特殊字符:资源属性可能包含非字母数字字符。
- UTF-8 编码:使用 Prometheus 3.0,完整的 UTF-8 支持使得无需字符转义即可执行查询。
数据模型差异
| 方面 | Prometheus (旧版) | OpenTelemetry |
|---|---|---|
| 聚合时态性 | 仅限累积 | 累积或增量 |
| 直方图区间 | 带有 le 标签的显式存储桶 |
指数存储桶或显式存储桶 |
| 速率计算 | 始终使用 rate() 或 increase() |
取决于时态性 |
| 指标后缀 | 手动 (_total, _bucket) |
基于仪器类型的自动 |
OpenTelemetry 指标的 UTF-8 字符转义
Prometheus 3.0 及更高版本(建议)
借助 Prometheus 3.0 的 UTF-8 支持,可以使用其原始名称直接查询 OpenTelemetry 指标:
# Direct querying with UTF-8 support using curly braces
{"http.server.duration"}
# Query with complex label names
{"process.runtime.jvm.memory.usage"}{
"service.name"="my-service",
"jvm.memory.type"="heap"
}
旧版 Prometheus 版本
对于较旧的 Prometheus 版本,请使用 __name__ 标签来查询具有特殊字符的指标:
# Using __name__ for metrics with dots
{__name__="http.server.duration"}
# Combining with other label selectors
{__name__="http.server.duration", job="my-app"}
常见的 OpenTelemetry 指标名称模式
OpenTelemetry 指标遵循通常包括点的 语义约定 :
# HTTP metrics
{"http.server.duration"}
{"http.client.request.size"}
# System metrics
{"system.cpu.utilization"}
{"system.memory.usage"}
# Runtime metrics
{"process.runtime.jvm.memory.usage"}
{"process.runtime.go.gc.duration"}
处理聚合时态
查询 OpenTelemetry 指标时最关键的区别之一是了解聚合时态性。
累积时态
累积指标的工作方式类似于传统的 Prometheus 计数器,需要 速率计算:
# For cumulative HTTP request counts
rate({"http.server.request.count"}[5m])
# For cumulative HTTP durations (histograms)
rate({"http.server.duration_sum"}[5m]) /
rate({"http.server.duration_count"}[5m])
增量时间特性
增量指标表示自上次测量以来的变化,不应使用 rate() 或 increase():
# For delta HTTP request counts - NO rate() needed
{"http.server.request.count"}
# For delta HTTP durations
{"http.server.duration_sum"} / {"http.server.duration_count"}
确定时态性
遗憾的是,PromQL 无法自动检测时态性。 需要知道数据源:
- Prometheus:通常发送累积指标
- OpenTelemetry:混合,取决于 SDK 和配置
- 自定义导出程序:检查导出程序文档
时间性最佳实践
- 记录数据源:跟踪哪些指标使用哪个时态
- 使用一致的命名:考虑向指标名称添加时态提示
- 创建单独的仪表板:为累积指标和增量指标生成不同的视图
- 测试查询:验证速率计算是否生成预期结果与原始值相比
直方图查询模式
OpenTelemetry 直方图可以使用不同的存储桶策略。 Azure Monitor 托管的 Prometheus 实现在不同直方图类型上提供了增强的直方图函数支持。
支持的直方图函数
| 功能 | OTLP 显式直方图 | Prometheus 原生直方图/OTLP 指数直方图 | Prometheus 传统直方图 |
|---|---|---|---|
histogram_quantile |
histogram_quantile(0.9, sum by (cluster, le) (rate({"http.request.duration"}[5m]))) 注意: le 是仅在查询期间存在的虚构标签 |
histogram_quantile(0.9, sum by (cluster) (rate({"http.request.duration"}[5m]))) |
histogram_quantile(0.9, sum by (cluster, le) (rate({"http.request.duration_bucket"}[5m]))) |
histogram_avg |
histogram_avg(rate({"http.request.duration"}[5m])) |
histogram_avg(rate({"http.request.duration"}[5m])) |
不支持 |
histogram_count |
histogram_count(rate({"http.request.duration"}[5m])) |
histogram_count(rate({"http.request.duration"}[5m])) |
不支持 |
histogram_sum |
histogram_sum(rate({"http.request.duration"}[5m])) |
histogram_sum(rate({"http.request.duration"}[5m])) |
不支持 |
histogram_fraction |
不支持 | histogram_fraction(0, 0.2, rate({"http.request.duration"}[1h])) |
不支持 |
histogram_stddev |
不支持 | 已支持 | 不支持 |
histogram_stdvar |
不支持 | 已支持 | 不支持 |
注释
Azure Monitor 的托管 Prometheus 提供了超越开源 Prometheus 的增强直方图支持。 处理 OTLP 显式直方图的所有直方图函数(histogram_avg、histogram_count、histogram_sum)都是 Azure 特定的增强功能,目前在开源 Prometheus 中无法使用。 有关标准 Prometheus 直方图支持,请参阅 histogram_quantile。
Azure Monitor 直方图实现详细信息
在 Azure Monitor 中查询直方图指标时,请记住以下性能注意事项:
直方图指标上的非直方图函数:当将非直方图Functions 应用于直方图指标时,该函数仅对总和值进行操作,不会从数据存储中检索存储桶值。
直方图查询成本:直方图函数查询的直方图指标的成本至少比正常计数器样本高出 10.5 倍。 在以下情况下,请考虑以下事项:
- 对直方图数据执行长时间回溯
- 在高基数指标上应用直方图函数
- 设计可能接近查询限制阈值的查询
在应用直方图函数之前,使用 记录规则 预先聚合和减少基数。
显式直方图(旧版兼容)
# Calculate percentiles from explicit buckets - requires 'le' in group by
histogram_quantile(0.99,
sum by ("service.name", le) (rate({"http.server.request.duration"}[2m]))
)
# 95th percentile without additional grouping dimensions
histogram_quantile(0.95,
sum by (le) (rate({"http.server.duration_bucket"}[5m]))
)
# Average duration using histogram_avg (Azure Monitor enhancement)
histogram_avg(rate({"http.server.request.duration"}[5m]))
# Ensure you have the correct temporality:
# - Use rate() for cumulative histograms
# - Use raw values for delta histograms
指数直方图
指数直方图提供自动存储桶大小调整,不使用 'le' 标签:
# Native histogram queries (Prometheus 3.0+) - no 'le' needed
histogram_quantile(0.99,
sum by ("service.name") (rate({"http.server.request.duration"}[2m]))
)
# 95th percentile without grouping dimensions
histogram_quantile(0.95,
rate({"http.server.duration"}[5m])
)
# Calculate fraction of requests under 200ms
histogram_fraction(0, 0.2, rate({"http.server.request.duration"}[1h]))
资源属性处理
OpenTelemetry 资源属性将成为可筛选的 PromQL 标签:
# Service identification
{__name__="http.server.duration", "service.name"="frontend"}
# Environment separation
{__name__="http.server.duration", "deployment.environment"="production"}
# Grouping on unique cloud resources
Count by ("Microsoft.resourceid") ({"http.server.duration"})
注释
不建议对保留的 "__name__" 标签使用正则表达式筛选,以获得最佳查询性能。 避免 {__name__=~“http.*”} 等模式。
查询优化提示
限制高基数指标的时间范围
# Be cautious with broad queries over long time ranges
sum by ("service.name") ({"http.server.duration"}[1h])
尽可能提前聚合
# Better - aggregate before complex operations
sum(rate({"http.server.request.count"}[5m])) by ("service.name")
# Avoid - complex operations on high cardinality labels unless necessary
rate(sum({"http.server.request.count"}[5m]) by ("service.name", "http.method", "http.status_code"))
有关聚合运算符的详细信息,请参阅 Prometheus 聚合运算符。
排查常见问题
名称中带点的指标缺失
问题:查询不返回指标的数据,例如 http.server.duration。
解决方案:使用大括号或 __name__ 选择器进行 UTF-8 引用:
# Try UTF-8 quoting with curly braces first
{"http.server.duration"}
# Fallback to __name__
{__name__="http.server.duration"}
错误的比率计算
问题:速率计算显示意外的峰值或下降。
解决方案:验证时态并调整查询:
# For cumulative metrics
rate({"http.server.request.count"}[5m])
# For delta metrics (no rate needed)
{"http.server.request.count"}
标签名称冲突
问题:OpenTelemetry 资源属性与 Prometheus 约定冲突。
解决方案:使用显式标签选择:
# Specify the exact label name
{"service.name"="my-service"}
# Avoid regex when possible
{"service.name"!~"other-service"}