请参与 Prometheus 用户调研(2026 年 3 月版) ,帮助社区确定未来开发工作的优先级!

使用 Prometheus 作为您的 OpenTelemetry 后端

Prometheus 支持通过 OTLP (即“OpenTelemetry 协议”)通过 HTTP  进行摄入。

启用 OTLP 接收器

默认情况下,OTLP 接收器是禁用的,这与远程写入 (Remote Write) 接收器类似。这是因为 Prometheus 可以在没有任何身份验证的情况下工作,因此除非显式配置,否则接受传入流量并不安全。

要启用该接收器,您需要启用 CLI 标志 --web.enable-otlp-receiver。这将使 Prometheus 在 HTTP /api/v1/otlp/v1/metrics 路径上提供 OTLP 指标接收服务。

$ prometheus --web.enable-otlp-receiver

向 Prometheus 服务器发送 OpenTelemetry 指标

通常,您需要告知 OTLP 指标流量的源头关于 Prometheus 端点的信息,以及必须使用 OTLP 的 HTTP  模式(gRPC 通常是默认值)。

OpenTelemetry SDK 和仪器化库通常可以通过标准环境变量 进行配置。以下是将 OpenTelemetry 指标发送到 localhost 上的 Prometheus 服务器所需的 OpenTelemetry 变量。

export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=https://:9090/api/v1/otlp

注意

关闭追踪和日志

export OTEL_TRACES_EXPORTER=none
export OTEL_LOGS_EXPORTER=none

OpenTelemetry 指标的默认推送间隔为 60 秒。以下设置会将推送间隔设为 15 秒。

export OTEL_METRIC_EXPORT_INTERVAL=15000

如果您的仪器化库没有开箱即用地提供 service.nameservice.instance.id,强烈建议您手动设置它们。

export OTEL_SERVICE_NAME="my-example-service"
export OTEL_RESOURCE_ATTRIBUTES="service.instance.id=$(uuidgen)"

上述内容假设您的系统中可以使用 uuidgen 命令。请确保 service.instance.id 对于每个实例都是唯一的,并且每当资源属性发生变化时都会生成一个新的 service.instance.id推荐的 做法是在每次实例启动时生成一个新的 UUID。

配置 Prometheus

本节介绍启用和调优 OpenTelemetry 流程的各种推荐的 Prometheus 服务器配置方面。

请参阅我们在下文中使用的示例 Prometheus 配置文件 文件 

启用无序摄入

您可能希望启用无序摄入的原因有很多。

例如,OpenTelemetry 收集器鼓励批处理,并且您可能有多个收集器副本向 Prometheus 发送数据。由于没有对这些样本进行排序的机制,它们可能会乱序到达。

要启用无序摄入,您需要使用以下内容扩展 Prometheus 配置文件:

storage:
  tsdb:
    out_of_order_time_window: 30m

30 分钟的无序窗口已足以应对大多数情况,但请根据您的需求随时调整此值。

提升资源属性

根据我们的经验以及与社区的交流,我们发现,在所有常见的资源属性中,有些属性值得附加到您的所有 OTLP 指标中。

默认情况下,Prometheus 不会提升任何属性。如果您想提升其中任何属性,可以在 Prometheus 配置文件的这一部分进行操作。以下代码片段分享了提升属性的最佳实践。

otlp:
  # Recommended attributes to be promoted to labels.
  promote_resource_attributes:
    - service.instance.id
    - service.name
    - service.namespace
    - service.version
    - cloud.availability_zone
    - cloud.region
    - container.name
    - deployment.environment
    - deployment.environment.name
    - k8s.cluster.name
    - k8s.container.name
    - k8s.cronjob.name
    - k8s.daemonset.name
    - k8s.deployment.name
    - k8s.job.name
    - k8s.namespace.name
    - k8s.pod.name
    - k8s.replicaset.name
    - k8s.statefulset.name

在查询时包含资源属性

所有 OTel 资源属性(默认情况下除 service.instance.idservice.namespaceservice.name 外)都会被转换为特殊指标 target_info 上的标签。这意味着,对于您没有提升的 OTel 资源属性,您仍然可以通过与 target_info 进行连接,在查询中包含相应的标签。为了实现这一点,我们建议通过以下标志启用实验性 PromQL 函数 info,以便于进行连接。

--enable-feature=promql-experimental-functions

此类查询的一个示例如下:

info(rate(http_server_request_duration_seconds_count[2m]), {k8s_cluster_name=~".+"})

或者,通过原始的连接查询也可以实现同样的效果:

rate(http_server_request_duration_seconds_count[2m])
* on (job, instance) group_left (k8s_cluster_name)
target_info

上述两个查询中发生的情况是,rate(http_server_request_duration_seconds_count[2m]) 产生的时序数据通过共享相同 jobinstance 标签的 target_info 系列中的 k8s_cluster_name 标签进行了增强。换句话说,jobinstance 标签在 http_server_request_duration_seconds_counttarget_info 之间共享,类似于 SQL 外键。另一方面,k8s_cluster_name 标签对应于 OTel 资源属性 k8s.cluster.name(除非另有配置,Prometheus 会将点号转换为下划线)。

请注意,info 函数通常比原始连接查询性能更高,因为它只选择具有匹配 jobinstance 标签的 target_info 系列。或许更重要的是,info 函数解决了连接查询方法中一个古老且晦涩的问题。当除被连接标签(即所谓的标识标签)之外的其他标签值发生变化(即流失)时,除非旧的 target_info 版本被标记为过时,否则在 PromQL 回溯增量(默认为 5 分钟)期间,旧版本和新版本的 target_info 会出现重叠。在此期间,针对 target_info 的连接查询会失败,因为存在两个匹配的不同 target_info 时序。幸运的是,info 函数不会受到这个问题的影响,因为它总是选取具有最新样本的时序!

那么,target_info 指标与 OTel 资源属性之间的关系是什么?当 Prometheus 处理 OTLP 写入请求时,如果包含的资源包含属性 service.instance.id 和/或 service.name,Prometheus 就会为每个(OTel)资源生成信息指标 target_info。它为每个此类 target_info 系列添加标签 instance(值为 service.instance.id 资源属性),以及标签 job(值为 service.name 资源属性)。如果存在资源属性 service.namespace,它会作为 job 标签值的前缀(即 <service.namespace>/<service.name>)。

默认情况下,service.nameservice.namespaceservice.instance.id 本身不会添加到 target_info 中,因为它们已被转换为 jobinstance。但是,可以启用以下配置参数,将它们直接添加到 target_info 中(如果 otlp.translation_strategyUnderscoreEscapingWithSuffixes,则通过规范化将点号替换为下划线),以此作为对转换为 jobinstance 的补充。

otlp:
  keep_identifying_resource_attributes: true

其余的资源属性也会作为标签添加到 target_info 系列中,如果 otlp.translation_strategyUnderscoreEscapingWithSuffixes,名称将转换为 Prometheus 格式(例如点号转换为下划线)。如果资源缺少 service.instance.idservice.name 属性,则不会生成相应的 target_info 系列。

对于资源的每个 OTel 指标,Prometheus 会将其转换为相应的 Prometheus 时序,并(如果已生成 target_info)为其添加正确的 instancejob 标签。

UTF-8

从 3.x 版本开始,Prometheus 支持指标名称和标签使用 UTF-8,因此可以省略 OpenTelemetry 的 Prometheus 规范化转换器包 。注意,当 Prometheus 通过内容协商宣布允许 UTF-8 字符时,它并不要求指标名称必须包含以前不支持的字符。OTLP 指标可以以多种不同的方式进行转换,具体取决于端点的配置。因此,虽然 Prometheus 存储和 UI 中默认启用了 UTF-8,但您需要为 OTLP 指标接收器设置 translation_strategy,其默认设置为旧的规范化方式 UnderscoreEscapingWithSuffixes

共有四种可能的转换策略,其中两种需要启用 Prometheus 的 UTF-8 支持:

  • UnderscoreEscapingWithSuffixes(默认值)。这会完全转义经典 Prometheus 指标名称兼容性 的指标名称,并附加类型和单位后缀。
  • UnderscoreEscapingWithoutSuffixes。这会以类似于 UnderscoreEscapingWithSuffixes 的方式完全转义指标名称,但不会附加类型和单位后缀。从多个角度来看,这种模式都是不可取的,用户应注意缺少后缀可能会导致指标名称冲突,因此仅在经过仔细测试的情况下才启用此模式。一些更倾向于 OTel 对称性和有限字符支持之间平衡的组织会使用此模式。
  • NoUTF8EscapingWithSuffixes 将禁用将特殊字符更改为 _,这允许原生使用 OpenTelemetry 指标格式,尤其是配合 语义约定  使用时。请注意,为了防止多个相同名称但类型或单位不同的指标之间发生潜在冲突,将附加单位和 _total(针对计数器)等特殊后缀。此模式需要启用 UTF-8。
  • NoTranslation。此策略绕过所有指标和标签名称转换,直接传递它们。此模式需要启用 UTF-8。请注意,如果没有后缀,当多个相同名称但类型或单位不同的指标存在时,可能会发生冲突。
otlp:
  # Ingest OTLP data keeping UTF-8 characters in metric/label names.
  translation_strategy: NoTranslation

Delta 时间性

OpenTelemetry 规范表明 同时支持 Delta 时间性和累积 (Cumulative) 时间性。虽然 Delta 时间性在 statsd 和 graphite 等系统中很常见,但累积时间性是 Prometheus 中的默认设置。

目前,Prometheus 嵌入了来自 OpenTelemetry-Collector-contrib delta 到累积处理器 ,该处理器能够在存储到 Prometheus TSDB 之前摄入 Delta 并将其转换为等效的累积表示。

此功能是实验性的,因此请在启动 Prometheus 时启用功能标志 otlp-deltatocumulative 以使用它。

团队目前仍在致力于开发一种更有效的处理 OTLP Delta 的方法。

本页内容