Prometheus 和 OpenMetrics 兼容性

状态: 开发中

Prometheus 格式之间的区别

本文档涵盖了 OpenTelemetry 与各种 Prometheus 相关格式的兼容性,包括

用于抓取指标(pull)的格式

用于推送指标的格式

下文将“Prometheus”一词用于指代所有这些格式的集合,即使某些功能可能在特定格式中缺失。为了避免重复每种格式的规范,本文档将包含可能无法在所有 Prometheus 格式中实现的要求。在撰写本文时,以下功能不支持:

  • Prometheus 文本暴露格式目前不支持 Exemplars。
    • 如果 Exemplars 不受支持,则必须将其丢弃。
  • Prometheus 文本暴露格式或 Prometheus protobuf 格式目前不支持 Info 和 StateSet 类型的指标。
    • 如果规范要求生成 Prometheus Info 类型指标,但 Info 类型指标不受支持,则必须生成一个带有附加 _info 名称后缀的 Prometheus Gauge。
    • 如果规范要求生成 Prometheus StateSet 类型指标,但 StateSet 类型指标不受支持,则必须改用 Prometheus Gauge。
  • 指数(原生)直方图目前在 Prometheus 文本暴露格式或 OpenMetrics 文本/proto 格式中不受支持。
    • 指数(原生)直方图应被丢弃(如果不支持),或可转换为固定桶直方图。

Prometheus 指标指向 OTLP

指标元数据

Prometheus 指标名称MUST被添加为 OTLP 指标的名称。默认情况下,名称不应被修改,但翻译应提供配置,启用后可移除类型(例如 _total)和单位(例如 _seconds)后缀。

Prometheus UNIT 元数据(如果存在)MUST被转换为 OTLP 指标的单位。单位应通过以下方式从 Prometheus 约定转换为 OpenTelemetry 约定:

  • 从全词转换为缩写(例如,“milliseconds”转换为“ms”)。
  • 特殊情况:将“ratio”转换为“1”。
  • 将“foo_per_bar”转换为“foo/bar”。

Prometheus HELP 元数据(如果存在)MUST被添加为 OTLP 指标的描述。

Prometheus TYPE 元数据(如果存在)MUST被用于确定 OTLP 数据类型,并决定下面列出的特定类型转换规则。没有类型元数据的指标系列遵循下面“未知类型”的规则。TYPE 元数据也必须被添加到 OTLP metric.metadataprometheus.type 键下(例如 prometheus.type="unknown")。

计数器

Prometheus CounterMUST被转换为具有 is_monotonic 等于 true 的 OTLP Sum。

计量器

Prometheus GaugeMUST被转换为 OTLP Gauge。

Info

Prometheus Info 指标MUST被转换为 OTLP Non-Monotonic Sum,除非它是用于填充资源属性的 target info 指标。Prometheus Info 指标可以被看作是 Prometheus Gauge 指标的一个特殊情况,其值为 1,并且其标签在进程生命周期内通常保持不变。它被转换为 OTLP Non-Monotonic Sum,而不是 OTLP Gauge,因为值 1 被视为一个计数,在聚合掉标签时应将它们加起来。

StateSet

Prometheus StateSet 指标MUST被转换为 OTLP Non-Monotonic Sum。Prometheus StateSet 指标可以被看作是 Prometheus Gauge 指标的一个特殊情况,其值为 0 或 1,并且每个可能的状态都有一个指标点。它被转换为 OTLP Non-Monotonic Sum,而不是 OTLP Gauge,因为值 1 被视为一个计数,在聚合掉标签时应将它们加起来。

未知类型

Prometheus UnknownMUST被转换为 OTLP Gauge。

直方图

Prometheus HistogramMUST被转换为 OTLP Histogram。

多个 Prometheus 直方图指标MUST被合并成一个 OTLP Histogram。

  • _bucket 后缀指标上的 le 标签用于识别和排序直方图桶边界。每个 Prometheus 行产生直方图中的一个桶计数。除了 +Inf 之外,le 标签的每个值都会产生一个桶边界。
  • 带有 _count_sum 后缀的行用于确定直方图的计数和总和。
  • 如果 _count 不存在,则该指标MUST被丢弃。
  • 如果 _sum 不存在,则直方图的总和MUST被置空。

原生直方图

具有标准(指数)模式(即模式 -4 到 8)且为整数和计数器 flavors 的 Prometheus Native Histogram MUST 被转换为 OTLP Exponential Histogram,如下所示:

  • Schema 被转换为 Exponential Histogram Scale
  • 如果 Sum 等于 Stale NaN 值,则 NoRecordedValue 标志设置为 true。否则,
    • Count 被转换为 Exponential Histogram Count
    • Sum 被转换为 Exponential Histogram Sum
  • Timestamp 在将毫秒转换为纳秒后,被转换为 Exponential Histogram TimeUnixNano
  • ZeroCount 被直接转换为 Exponential Histogram ZeroCount
  • ZeroThreshold 被转换为 Exponential Histogram ZeroThreshold
  • PositiveSpansPositiveDeltas 表示的稀疏桶布局被转换为由 Positive 桶计数和 Offset 表示的 Exponential Histogram 密集布局。负数同理。请注意,Prometheus Native Histograms 的桶由上边界索引,而 Exponential Histograms 由下边界索引,因此 Offset 字段会相差一。
  • MinMax 不设置。
  • StartTimeUnixNano 设置为 Created 时间戳(如果可用)。
  • AggregationTemporality 设置为 cumulative

浮点型或仪表盘型的原生直方图MUST被丢弃。

Schema 范围之外的原生直方图MUST被丢弃。

摘要

Prometheus SummaryMUST被转换为 OTLP Summary。

多个 Prometheus 指标被合并成一个 OTLP Summary。

  • 摘要指标上非后缀的 quantile 标签用于识别摘要指标中的分位数点。每个 Prometheus 行会产生一个摘要分位数。
  • 带有 _count_sum 后缀的行用于确定摘要的计数和总和。
  • 如果 _count 不存在,则该指标MUST被丢弃。
  • 如果 _sum 不存在,则摘要的总和MUST被设置为零

已丢弃类型

以下 Prometheus 类型MUST被丢弃:

开始时间

Prometheus Cumulative 指标可以使用 _created 样本系列来包含开始时间。当转换 Prometheus Counter 到 OTLP 时,如果有 _created,则应使用它。如果没有 _created 指标,则默认情况下,转换必须遵循 Cumulative streams: handling unknown start time。转换可以提供一个默认禁用的配置选项,允许使用 process_start_time_seconds 指标来提供开始时间。仅当目标上的所有计数器在进程启动后才开始,并且在进程运行时不重置时,使用 process_start_time_seconds 才是正确的。

Exemplars

Prometheus Exemplars可以附加到 Prometheus Histogram 桶指标点和计数器指标点。直方图桶上的 Exemplars 应被转换为 OpenTelemetry 直方图上的 Exemplars。计数器指标点上的 Exemplars 应被转换为 OpenTelemetry Sums 上的 Exemplars。如果存在,时间戳必须被添加到 OpenTelemetry exemplar 中。Trace ID 和 Span ID 应分别从 trace_idspan_id 标签键中检索。未用于 trace 和 span ID 的所有标签必须作为属性被添加到 OpenTelemetry exemplar 中。

Instrumentation Scope

带有 otel_scope_ 前缀的标签MUST被从所有指标点中丢弃,并用作 Instrumentation Scope 名称(otel_scope_name)、版本(otel_scope_version)、Schema URL(otel_scope_schema_url)、属性(otel_scope_[attribute])。

# TYPE http_server_duration counter
http_server_duration{otel_scope_name="go.opentelemetry.io.contrib.instrumentation.net.http.otelhttp",otel_scope_schema_url="/schemas/1.31.0",otel_scope_version="v0.24.0",otel_scope_library_mascot="gopher"...} 1

变成

# within a resource_metrics
scope_metrics:
  scope:
    name: go.opentelemetry.io.contrib.instrumentation.net.http.otelhttp
    version: v0.24.0
    attributes:
      library_mascot: gopher
  schema_url: /schemas/1.31.0 
  metrics:
  - name: http_server_duration
    data:
      sum:
        data_points:
        - value: 1

不带 otel_scope_ 前缀标签的指标MUST被分配一个标识执行 Prometheus 到 OpenTelemetry 翻译的实体的 instrumentation scope(例如,collector 的 prometheus receiver)。

资源属性

抓取 Prometheus 端点时,资源属性MUST被添加到抓取的指标中,以区分来自其他 Prometheus 端点的指标。特别是,service.nameservice.instance.id 是必需的,以便 Prometheus exporters 可以使用 jobinstance 标签来区分指标,如下所述

以下属性MUST被关联到抓取的指标作为资源属性,且MUST NOT被添加为指标属性:

OTLP 资源属性描述
service.name目标所属服务的已配置名称
service.instance.id目标的唯一标识符。默认情况下,它应该是抓取 URL 的 <host>:<port>

以下属性SHOULD被关联到抓取的指标作为资源属性,且MUST NOT被添加为指标属性:

OTLP 资源属性描述
server.address抓取目标的 URL 的 <host> 部分。
server.port抓取目标的 URL 的 <port> 部分。
url.schemehttphttps

除了上述属性外,target info 指标用于提供额外的资源属性。如果存在,target info 指标MUST被从指标批次中丢弃,并且 target info 指标的所有标签MUST被转换为资源属性,附加到抓取中所有其他指标上。默认情况下,标签键和值MUST NOT被修改(例如,替换键中的 _. 字符)。

OTLP 指标指向 Prometheus

指标元数据

Prometheus Pull exporters MUST NOT 在 Prometheus 端点的单次抓取中返回同一指标名称的重复 UNIT、HELP 或 TYPE 注释。Exporters MUST 丢弃整个指标以防止冲突的 TYPE 注释,但 SHOULD NOT 因冲突的 UNIT 或 HELP 注释而丢弃指标点。相反,除一个冲突的 UNIT 和 HELP 注释外(但不是指标点),SHOULD 被丢弃。如果丢弃注释或指标点,exporter SHOULD 通过错误日志记录向用户发出警告。

OTLP 指标的名称MUST被添加为 Prometheus 指标名称。Prometheus 命名约定鼓励指标名称匹配正则表达式:[a-zA-Z_:]([a-zA-Z0-9_:])*。不推荐使用的字符SHOULD默认替换为 _ 字符,以实现与 Prometheus 约定的兼容性。多个连续的 _ 字符SHOULD被替换为单个 _ 字符。

OTLP 指标点的单位SHOULD在可能的情况下转换为 Prometheus 中的等效单位。这包括:

  • 从缩写转换为全词(例如,“ms”转换为“milliseconds”)。
  • 删除括号内的单位部分(例如,{packet})。括号MUST NOT包含在生成的单位中。“count of foo”在 Prometheus 中被视为无单位。
  • 特殊情况:将“1”转换为“ratio”。
  • 将“foo/bar”转换为“foo_per_bar”。

生成的单位SHOULD被添加为 UNIT 元数据。单位后缀SHOULD被添加到指标名称中,除非指标名称已以单位结尾(在类型特定后缀之前)。单位后缀位于任何类型特定后缀之前。

OTLP 指标点的描述MUST被添加为 HELP 元数据

OTLP 指标的数据点类型MUST被添加为 TYPE 元数据。它也决定了下面列出的特定类型转换规则。

Instrumentation Scope

Prometheus exporters MUST 默认情况下,根据原始数据点所属的 scope,将 scope 名称作为 otel_scope_name 标签,scope 版本作为 otel_scope_version 标签,scope Schema URL 作为 otel_scope_schema_url 标签,scope 属性作为带有 otel_scope_ 前缀的标签(遵循下面 Metric Attributes 部分的规则),添加到所有指标点上。名称为 ‘name’、‘version’ 或 ‘schema_url’ 的 scope 属性MUST被丢弃,以避免与已有的 otel_scope_nameotel_scope_versionotel_scope_schema_url 标签冲突。

计量器

如果 metric.metadataprometheus.type 键为 unknown,则 OpenTelemetry GaugeMUST被转换为 Prometheus Unknown 类型指标。否则,它MUST被转换为 Prometheus Gauge。

求和

OpenTelemetry Sums 遵循以下逻辑:

  • 如果聚合临时性是 cumulative 且 sum 是单调的,则它MUST被转换为 Prometheus Counter。
  • 如果聚合临时性是 cumulative,sum 是非单调的,并且 metric.metadataprometheus.type 键是 info,则它MUST被转换为 OpenMetrics Info 指标。
  • 如果聚合临时性是 cumulative,sum 是非单调的,并且 metric.metadataprometheus.type 键是 stateset,则它MUST被转换为 OpenMetrics StateSet 指标。
  • 如果聚合临时性是 cumulative 且 sum 是非单调的,则它MUST被转换为 Prometheus Gauge。
  • 如果聚合临时性是 delta 且 sum 是单调的,则它 SHOULD 被转换为 cumulative 临时性并成为 Prometheus Counter。预期行为如下:
    • 新的数据点类型必须与累积的数据点类型相同。
    • 新的数据点的开始时间必须与累积数据点的时间匹配。如果不匹配,请参阅 检测对齐问题
  • 否则,它MUST被丢弃。

如果单调 Sum 指标点的指标名称不以 _total 后缀结尾,则默认 SHOULD 添加 _total 后缀,否则名称MUST保持不变。Exporters SHOULD 提供一个配置选项来禁用 _total 后缀的添加。具有 StartTimeUnixNano 的单调 Sum 指标点也应导出 {name}_created 指标。

直方图

具有 cumulative 聚合临时性的 OpenTelemetry Histogram MUST 被转换为具有以下指标的 Prometheus 指标系列:

  • 一个表示直方图 count 字段的 {name}_count 指标。直方图点的所有属性都转换为 Prometheus 标签。
  • 表示直方图 sum 字段的 {name}_sum 指标,仅在 sum 为正且单调时报告。当所有桶都为正数时,sum 为正且单调。直方图点的所有属性都转换为 Prometheus 标签。
  • 一系列 {name}_bucket 指标点,包含所有直方图点的属性作为标签。此外,添加一个名为 le 的标签,表示桶边界。标签的值是桶边界的字符串化浮点值,按从小到大的顺序排列。每个点的值是截至 le 标签中报告的边界的所有直方图桶计数的总和。这些点将包含一个落在 le 标签内且没有其他 le 标签点的 Exemplar。最后一个桶指标 MUST 有一个 +Inf 阈值。
  • 具有 StartTimeUnixNano 的直方图也应导出 {name}_created 指标。

具有 Delta 聚合临时性的 OpenTelemetry Histograms SHOULD 被聚合为 Cumulative 聚合临时性并遵循上述逻辑,或 MUST 被丢弃。

指数直方图

具有 cumulative 聚合临时性的 OpenTelemetry Exponential Histogram MUST 被转换为 Prometheus Native Histogram,如下所示:

  • Scale 被转换为 Native Histogram Schema。目前,有效值为 -4 <= n <= 8。如果 Scale > 8,则 Exponential Histogram 数据点 SHOULD 被降采样到 Prometheus 可接受的范围([-4,8])内。任何无法重新缩放到可接受范围的数据点MUST被丢弃。
  • 如果 NoRecordedValue 标志设置为 false,则 Count 被转换为 Native Histogram Count,否则,Native Histogram Count 设置为 Stale NaN 值。
  • 如果 Sum 已设置且 NoRecordedValue 标志设置为 false,则 Sum 被转换为 Native Histogram Sum,否则,Native Histogram Sum 设置为 Stale NaN 值。
  • TimeUnixNano 在将纳秒转换为毫秒后,被转换为 Native Histogram Timestamp
  • ZeroCount 被直接转换为 Native Histogram ZeroCount
  • ZeroThreshold(如果已设置)被转换为 Native Histogram ZeroThreshold。否则,它被设置为默认值 1e-128
  • Positive 桶计数和 Offset 表示的密集桶布局被转换为由 PositiveSpansPositiveDeltas 表示的 Native Histogram 稀疏布局。负数同理。注意,Prometheus Native Histograms 的桶由上边界索引,而 Exponential Histograms 由下边界索引,因此 Offset 字段会相差一。
  • MinMax 不使用。
  • StartTimeUnixNano 不使用。

OpenTelemetry Exponential Histogram 具有 delta 聚合临时性的指标将被丢弃。

摘要

OpenTelemetry Summary MUST 被转换为具有以下指标的 Prometheus 指标系列:

  • 一个表示 summary count 字段的 {name}_count 指标。summary 点的所有属性都转换为 Prometheus 标签。
  • 表示 summary sum 字段的 {name}_sum 指标,仅在 sum 为正且单调时报告。summary 点的所有属性都转换为 Prometheus 标签。
  • 一系列 {name} 指标点,包含所有 summary 点的属性作为标签。此外,添加一个名为 quantile 的标签,表示报告的分位数点,其值为分位数(0.0 和 1.0 之间)的字符串化浮点值,按从低到高排列,且均为非负数。每个点的值是分位数点的计算值。
  • 具有 StartTimeUnixNano 的 Summary 也应导出 {name}_created 指标。

指标属性

OpenTelemetry 指标属性MUST被转换为 Prometheus 标签。字符串属性值直接转换为指标属性,非字符串属性值MUST遵循 属性规范被转换为字符串属性。Prometheus 命名约定鼓励指标名称匹配以下正则表达式:[a-zA-Z_]([a-zA-Z0-9_])*。不推荐使用的字符SHOULD被替换为 _ 字符。多个连续的 _ 字符SHOULD被替换为单个 _ 字符。这可能导致在多个相似名称的属性在同一位置共享无效字符的情况下产生歧义。在这种不太可能的情况下,如果多个键值对被转换为具有相同的 Prometheus 键,则值MUST用 ; 分隔并联接在一起,并按原始键的字典顺序排列。

Exemplars

OpenTelemetry 直方图和单调求和上的 示例 应该转换为 Prometheus 示例。其他 OpenTelemetry 数据点上的示例必须被丢弃。对于 Prometheus Remote Write 导出器,每个桶可以添加多个示例,因此所有示例都应该被转换。对于 Prometheus pull 端点,每个桶只能添加一个示例,因此如果附加示例,则必须使用每个桶中的最大示例。如果一个桶上不存在示例,则必须使用较低桶中的最高示例,即使它是另一个桶示例的重复。Prometheus 示例必须分别使用 trace_idspan_id 键来表示跟踪 ID 和 span ID。时间戳必须作为 Prometheus 示例上的时间戳添加,并且 filtered_attributes 必须作为 Prometheus 示例上的标签添加,除非它们会超出 字符限制

资源属性

在 Prometheus 导出器中,如果 OpenTelemetry 资源不是 空的,它应该被转换为一个 target 信息指标。资源属性可以根据导出器配置的要求复制到导出的指标族的标签中,否则必须被丢弃。target 信息指标必须是一个 info 类型指标,其标签必须包含资源属性,并且除了 jobinstance 标签外,不得包含任何其他标签。

在 Collector 的 Prometheus 导出器中,来自多个目标的指标可能会一起发送,因此必须区分不同的目标。然而,Prometheus 公开格式和 remote-write 格式不包含资源的概念,并且期望指标标签来区分抓取的目标。约定上,jobinstance 标签用于区分目标,并且期望出现在 Prometheus pull 导出器(“联合” Prometheus 端点)上公开的指标或通过 Prometheus remote-write 推送的指标上。在 OpenTelemetry 语义约定中,service.nameservice.namespaceservice.instance.id 三元组 要求唯一,这使得它们成为构建 jobinstance 的良好选择。在 Collector Prometheus 导出器中,service.nameservice.namespace 属性必须组合为 <service.namespace>/<service.name>,或者如果 namespace 为空则为 <service.name>,以形成 job 指标标签。如果存在 service.instance.id 属性,则必须将其转换为 instance 标签;否则,应将 instance 添加一个空值。其他资源属性应该被转换为一个 target 信息指标,否则必须被丢弃。target 指标是一个 info 类型指标,其标签必须包含资源属性,并且除了 jobinstance 之外,不得包含任何其他标签。每个唯一的 jobinstance 组合最多只能导出一条 target 信息指标。

如果语言 Prometheus 客户端库尚不支持 info 类型指标系列,则必须使用名为 target_info 的 gauge 类型指标系列,其恒定值为 1。

要将 OTLP 资源属性转换为 Prometheus 标签,字符串属性值将直接转换为标签,非字符串属性值必须按照 属性规范 转换为字符串属性。