帮你快速理解、总结文档立即下载
文档中心>实践教程>腾讯云可观测平台>上报自定义指标并同步到 Prometheus

上报自定义指标并同步到 Prometheus

最近更新时间:2026-10-14 09:36:02
本文档已由 AI 辅助审校
我的收藏
Prometheus 是一个功能强大、灵活且扩展性强的开源可观测平台,提供了多维数据模型、丰富的采集能力,以及强大的查询语言。作为 CNCF(Cloud Native Computing Foundation)旗下最重要的开源项目之一,Prometheus 在云原生时代被广泛使用,构建了繁荣的开源生态。特别是在指标(Metric)监控领域,Prometheus 已经成为了事实的标准。
腾讯云应用性能监控(APM)已实现与 Prometheus 的数据集成:对于通过 OpenTelemetry 方案接入 APM 的应用,可以使用 OpenTelemetry API 上报自定义指标,由 APM 服务端将数据同步到关联的 腾讯云 Prometheus 监控服务,用户无需自行部署 OpenTelemetry Collector 进行中转。

前置准备

1. 应用已通过 OpenTelemetry 方案接入 APM,并启用 OTLP 指标导出,具体接入方式请参考 应用接入概述。
2. 已创建与 APM 业务系统同地域的 Prometheus 监控服务实例,并具备访问权限,具体操作方式请参考 Prometheus 监控服务。

步骤1:关联 Prometheus 实例

在应用上报自定义指标之前,需要先建立 APM 业务系统和 Prometheus 实例之间的关联,并配置需要从 APM 服务端同步到 Prometheus 实例的指标。
1. 登录 APM 控制台,进入 系统配置 > Prometheus 集成 页面。
2. 在关联配置中,开启 Prometheus 关联,并选择当前地域的任何一个 Prometheus 实例。每个 APM 业务系统只能关联同一地域最多一个 Prometheus 实例。在当前账号第一次做关联操作的时候,需要授予 APM 访问 Prometheus 资源的权限,根据控制台的提示完成服务授权即可,系统会在访问管理(CAM)中自动创建名为 APM_QCSLinkedRoleInPromInstance 的角色。

3. 单击新增指标同步规则,指定需要同步到 Prometheus 实例的指标。
对于每一条同步规则,您可以基于精确匹配、前缀匹配以及后缀匹配这三种匹配方式来匹配指标名,也可以指定该规则的生效范围(可以是该业务系统的全部应用,或某一个具体的应用)。当 APM 服务端收到应用上报的自定义指标后,匹配同步规则的指标将被写入到关联的 Prometheus 实例中,不匹配同步规则的指标将被丢弃。
除了上报时填入的自定义标签外,APM 将额外增加 apm_instance 和 apm_service_name 两个标签,分别代表 APM 业务系统 ID 以及应用名,这样每一条 Prometheus 指标样本都能关联到唯一的 APM 应用。
说明:
写入到 Prometheus 实例的指标,将根据腾讯云 Prometheus 监控服务的计费规则产生相关的费用,详情请参见 Prometheus 计费概述。

步骤2:上报自定义指标

OpenTelemetry API 通过一系列的封装,让开发者可以轻松上手完成指标上报。我们以 Java 项目为例,演示如何通过 OpenTelemetry API 上报自定义指标。

重要对象

在编写代码的时候,需要使用到如下几个对象:
MeterProvider:MeterProvider 是使用 OpenTelemetry 指标 API 的唯一入口。通常情况下,在一个应用中只需要初始化一次。
Meter:Meter 由 MeterProvider 创建而成,用来创建 Instrument 对象。
Instrument:Instrument 对象用来记录测量数据。针对不同的指标类型以及不同编码模型(同步/异步),OpenTelemetry API 提供了一系列 Instrument 实现,包括 Counter、Asynchronous Counter、Histogram、Gauge、Asynchronous Gauge、UpDownCounter 等。

代码编写示例

1. 构建一个 Spring Boot 项目。
此步骤请参考 Spring Boot 官方文档,也可以将 Spring Boot 替换为任意一种 HTTP Server。
2. 引入 opentelemetry-api 依赖。请参考如下 Maven 配置引入 opentelemetry-api:
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-api</artifactId>
<version>1.35.0</version>
</dependency>
3. 创建 Instrument 对象。请参考如下代码创建 Instrument 对象:
@RestController
@RequestMapping("/metric")
public class MetricController {
// 把LongCounter作为成员变量
private LongCounter httpRequestCounter;
@PostConstruct
public void init() {
String scope = this.getClass().getName();
// 获取OpenTelemetry对象
OpenTelemetry openTelemetry = GlobalOpenTelemetry.get();
// 获取Meter对象。关于Scope的定义,请参考OpenTelemetry官方文档,一般情况下,可以使用class全名
Meter meter = openTelemetry.getMeter(scope);
// 创建LongCounter对象。在项目中创建1次即可
httpRequestCounter = meter.counterBuilder("http_request_total").setDescription("Counts HTTP request").build();
}
}
4. 计数。请参考如下代码片段,对 HTTP 请求进行计数:
@RestController
@RequestMapping("/metric")
public class MetricController {
// 定义一个Key为method的属性标签
private static final AttributeKey<String> METHOD_KEY = AttributeKey.stringKey("method");
/*
上个步骤中的初始化逻辑
*/
@RequestMapping("/order")
public String order() {
// order请求数+1
httpRequestCounter.add(1, Attributes.of(METHOD_KEY, "order"));
return "order + 1";
}
@RequestMapping("/pay")
public String pay() {
// pay请求数+1
httpRequestCounter.add(1, Attributes.of(METHOD_KEY, "pay"));
return "pay + 1";
}
}
对于其他语言编写的应用,上报自定义指标的方式与 Java 基本一致,具体请参见 OpenTelemetry 社区的 API/SDK 文档。
5. 接入 APM。
6. 触发数据上报。
启动应用,并多次访问 /metric/order 和 /metric/pay。探针会聚合计数并定期上报,Java 探针的默认上报间隔为 60 秒,可通过系统参数 otel.metric.export.interval 调整,单位为毫秒。

步骤3:通过 Grafana 查阅指标

上报完成后,前往关联的 Prometheus 实例,通过其关联的 Grafana 服务查询 http_request_total 指标,就能查看到上报的数据。接下来,可以基于 PromQL 语句实现复杂的查询,并通过 Grafana 自定义丰富的图表。



如果这个时候没有查到 http_request_total 指标,请确保在关联 Prometheus 实例的时候,针对此指标名配置了同步规则。对于不能匹配同步规则的指标,APM 服务端会进行丢弃处理。
由于 APM 在进行指标转换的时候,额外增加了 apm_instance 和 apm_service_name 两个标签,分别代表 APM 业务系统 ID 以及应用名,这样就可以基于这两个标签为业务系统和应用创建过滤条件。

附:指标转换原理

OpenTelemetry 旨在构建与语言无关,支持多种编程框架以及多种可观测平台的统一标准,所以在通过 OpenTelemetry 方案上报指标数据的应用场景中,Prometheus 并不是唯一的指标存储平台选择。因此,OpenTelemetry 的指标模型和 Prometheus 的指标模型不完全相同,在编写上报数据的代码之前,需要先了解从 OpenTelemetry 指标到 Prometheus 指标的转换逻辑。

OpenTelemetry 协议的数据模型

OpenTelemetry 的指标支持如下指标类型:
Gauge:表示瞬时值,一般情况下,Gauge 类型的数据点是不具备累加属性的,例如当前的温度、汽车的时速等。
Sum:表示一定时间间隔内所有测量值的总和。如果数据点是具备累加属性的,定义成 Sum 类型是更好的选择,例如 HTTP 请求数,网络流量等。如果测量值单调递增,Sum 可以被标识为单调的(monotonic)。对于单调的 Sum,后一个测量值永远不会小于前一个测量值,HTTP 请求数就符合这样的特征。
Histogram:表示通过聚合一定时间间隔内所有测量记录,以直方图的形式体现的数据类型。Histogram 包含通过聚合得到的 sum、count 字段,分别代表测量值的总和以及记录数。除此之外,还有可能包括表示最大值与最小值的 max、min 字段,以及一系列的数据桶(bucket)。每个数据桶会有明确的边界范围,以及落入到这个边界范围的记录数。Histogram 通过引入聚合机制,显著降低了指标数据量,同时也能提升数据的可读性。
ExponentialHistogram:ExponentialHistogram 是 Histogram 的替代表达形式,和 Histogram 的唯一区别在于 ExponentialHistogram 使用指数作为桶的边界,适合以较小的相对误差传达高动态范围数据。
Summary:Summary 通过分位数的形式表达数据,在最新的 OpenTelemetry 协议标准中,已经不推荐使用 Summary,所以尽可能不要使用这种数据点类型。
在 OpenTelemetry 指标协议中,对于 Sum、Histogram 和 ExponentialHistogram 类型,还支持两种不同的聚合时间性(Aggregation Temporality),用来区分数据是如何累加的,它们分别是:
增量(Delta):指标流的时间窗口不会重叠,相当于在指标流中随着时间的推移记录每个间隔时间段的数据增量。

image


累积(Cumulative):相当于在指标流中记录从“开始”以来的数据累积总和,“开始”通常意味着进程/应用程序的启动。

image


关于 OpenTelemetry 协议数据模型的更多详细介绍,请参见 OpenTelemetry 官方文档。

Prometheus 指标模型

Prometheus 包含如下几种指标模型,他们在定义上和 OpenTelemetry 的数据模型很类似,在本文中不再赘述,可以参考 Prometheus 官方文档获得详细信息:
Counter
Gauge
Histogram
Summary

模型映射

对于 OpenTelemetry 指标,将按照如下映射关系转换为 Prometheus 指标。



需要注意的是,Prometheus 的数据模型中,不能兼容增量聚合时间性(Delta Temporality),所以 APM 将直接丢弃使用 Delta 聚合时间性的 OpenTelemetry 指标。在 OpenTelemetry 提供的探针以及 SDK 中,存在名为 OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE 的环境变量,或者名为 otel.exporter.otlp.metrics.temporality.preference 的系统参数,用于指定聚合时间性(Delta Temporality),其默认值为 cumulative 或 CUMULATIVE。在保持默认值的情况下,不会发生因为兼容性导致的丢弃问题。
对于不单调递增的 Sum,由于 Prometheus 的 Counter 指标必须保持单调递增,因此不能直接保存为 Prometheus 的 Counter 指标。APM 会将其转换为 Prometheus 的 Gauge 指标。
对于 ExponentialHistogram,APM 会将其转换为 Prometheus 的 Histogram 指标,当然,这种转换会丢失一些精度。

Sum 的指标转换

Sum 类型的 OpenTelemetry 指标在转换为 Prometheus 指标(单调递增的 Sum 将转换为 Counter,非单调递增的 Sum 将转换为 Gauge)的时候,会遵循如下的转换原则:



这是比较容易理解的,OpenTelemetry 指标中的指标名、标签对、时间戳等字段会被原样输出到 Prometheus 的数据样本中,每个 OpenTelemetry 数据点对应一个 Prometheus 数据样本。值得注意的是,由于两种数据模型并不是完全一致,在转换为 Prometheus 指标的过程中,OpenTelemetry 指标中的部分信息将被忽略,其中包括开始时间(StartTimeUnixNano)、单位(Unit)、范例(Exemplar)等。

Gauge 类型的指标转换

Gauge 类型的 OpenTelemetry 指标在数据结构上与 Sum 类型类似,转换方式与 Sum 类型没有区别,本文不再赘述。

Histogram 类型的指标转换

Histogram 类型的 OpenTelemetry 指标在转换为 Prometheus 指标的时候,会遵循如下的转换原则:



每个 Histogram 类型的 OpenTelemetry 数据点,会被转化为多个 Prometheus 数据样本(Sample),具体的个数取决于 Histogram 类型的 OpenTelemetry 数据点中带有多少个桶(Bucket)。和 Sum 类型一样,标签对和时间戳会被原样输出到 Prometheus 的数据样本中,但在指标名和指标值的处理上,会经过一系列的转换。
首先,APM 会生成一个名为 指标名_sum 的 Prometheus 数据样本,取值为总和(sum)字段,代表所有原始记录的累加值总和。APM 还会生成一个名为 指标名_count 的 Prometheus 数据样本,取值为计数(count)字段,代表原始记录的总计数。
此外,每个来自 OpenTelemetry 的桶都会被转换成一个名为 指标名_bucket 的 Prometheus 数据样本,同时在此数据样本中添加一个标记为 le 的标签,表示该桶的边界。这些数据样本从低到高排列,每个点的值都是该数据样本 le 标签边界前所有桶的计数之和,从而转换成 Prometheus 中累加的 Histogram。之所以要这样转换,是因为在 Prometheus 的 Histogram 数据模型中,le 标签代表有多少条原始记录小于或等于一个特定的值,实际上就一定会包含前一个样本的计数。
最后,APM 会额外生成一个名为指标名_bucket 的 Prometheus 数据样本,并添加值为 +Inf 的 le 标签,其取值实际上就是计数(count)字段,代表原始记录的总计数。
因此,如果1个 Histogram 类型的 OpenTelemetry 数据点中带有 N 个桶(Bucket),将其转换为 Prometheus 指标后,会生成 N+3 条数据样本。

ExponentialHistogram 类型的指标转换

Prometheus 目前还没有支持 ExponentialHistogram,为了支持 ExponentialHistogram 类型的数据上报,APM 会先将 ExponentialHistogram 的桶边界转换成保留两位小数的 Histogram 桶边界,再进一步按照 Histogram 类型的指标转换规则进行处理。这样会丢失一些精度,所以不建议使用 ExponentialHistogram 类型上报数据。

Summary 类型的指标转换

Summary 类型的 OpenTelemetry 指标在转换为 Prometheus 指标的时候,会遵循如下的转换原则:



Summary 类型的转换规则和 Histogram 类似,如果1个 Summary 类型的 OpenTelemetry 数据点中带有 N 个分位数,将其转换为 Prometheus 指标后,会生成 N+2 条数据样本。由于在最近的 OpenTelemetry 协议标准中,已经不推荐使用 Summary,所以尽可能不要使用这种类型上报数据。