如何使用OpenTelemetry收集器将Prometheus提供的直方图数据转换为OTLP格式的数据
现代应用程序通常会通过 ` /metrics ` 端点以 Prometheus 格式公开各种指标数据。 在这些指标中,直方图尤其实用。它们能够显示数值落在不同区间的频率,比如 HTTP 请求的耗时、数据库查询的时间,或者队列处理的延迟等。 与简单的平均值不同,直方图能够呈现完整的图像:你可以清楚地看到有多少请求处理得很快,有多少请求处理得很慢,以及那些偶尔出现的异常值是如何影响用户体验的。 例如,在支付系统中,交易数量的突然增加可能会暴露出隐藏的瓶颈。虽然大多数请求会迅速完成,但那一小部分处理速度缓慢的交易却可能对整个系统产生连锁反应,导致重试次数增加、失败率上升,进而影响整体的吞吐量。直方图
现代应用程序通常会通过 `/metrics` 端点以 Prometheus 格式公开各种指标数据。
在这些指标中,直方图尤其实用。它们能够显示数值落在不同区间的频率,比如 HTTP 请求的耗时、数据库查询的时间,或者队列处理的延迟等。
与简单的平均值不同,直方图能够呈现完整的图像:你可以清楚地看到有多少请求处理得很快,有多少请求处理得很慢,以及那些偶尔出现的异常值是如何影响用户体验的。
例如,在支付系统中,交易数量的突然增加可能会暴露出隐藏的瓶颈。虽然大多数请求会迅速完成,但那一小部分处理速度缓慢的交易却可能对整个系统产生连锁反应,导致重试次数增加、失败率上升,进而影响整体的吞吐量。直方图通过展示数值的分布情况,并突出那些被平均值掩盖的异常值,帮助我们尽早发现这些问题。
然而,并非所有的后端服务都能原生理解 Prometheus 标准。许多现代的可观测性平台更倾向于使用 OTLP(OpenTelemetry 协议)。如果直接转发 Prometheus 数据而不进行转换,就可能会导致数据不完整或被错误解读。因此,我们需要一个流程来抓取、转换这些数据,并将其以 OTLP 格式导出,这样才能确保我们的可观测性系统能够保持一致性并具备实际操作价值。
在本文中,我们将使用 OpenTelemetry Collector 来从应用程序的 `/metrics` 端点抓取 Prometheus 直方图数据,将其映射到 OpenTelemetry 的直方图数据模型中,然后通过 OTLP 将这些数据导出到我们的可观测性后端系统中。Collector 充当了连接桥梁的角色,它在保证数据完整性的同时,也确保了与你的监控平台的兼容性。
为了具体说明这一过程,我们将使用一个模拟支付交易的小型 FastAPI 应用程序作为示例。该应用程序会公开两个 Prometheus 指标:`payment_transaction_duration_seconds`(用于记录每笔交易的耗时)和 `payment_transactions_total`(记录已完成交易的数量)。你也可以使用自己开发的应用程序来进行测试,因为任何在 `/metrics` 端点公开 Prometheus 数据的应用程序,其操作方式都是相同的。这就是我们将在本文中从头到尾使用的示例数据。
我们将涵盖的内容:
先决条件
在开始之前,请确保您具备以下条件:
已安装Docker
有一个应用程序,它通过
/metrics端点公开Prometheus指标拥有一个兼容OpenTelemetry的可观测性后端系统
具备关于Prometheus指标的基本知识
了解YAML语言的基础知识
对Docker和OpenTelemetry有基本的熟悉程度
阅读本教程并不需要掌握高级的OpenTelemetry知识。我会一步步讲解Prometheus直方图的工作原理,以及这些数据在通过OpenTelemetry收集器处理时会发生什么变化。
1. 如何使用Prometheus接收器抓取指标
首先,我们需要从应用程序中收集指标。演示应用程序会将它的Prometheus指标公开在/metrics端点上,而Prometheus接收器会定期访问这个端点,并将收集到的指标纳入可观测性处理流程中。您也可以直接查看/metrics端点上的数据,从而了解在收集器读取这些数据之前它们的实际内容。
配置示例:
receivers:
prometheus:
config:
scrape_configs:
- job_name: payment-demo
scrape_interval: 15s
staticConfigs:
- targets: ["payment-api:8080"]
这里背后实际发生了什么:
scrape_interval决定了收集器访问目标端点的频率。在这里我们设置了15秒的间隔;您可以根据自己对指标更新频率的需求,以及应用程序所能承受的负载来调整这个值。
在像支付平台或实时处理服务这样的高吞吐量系统中,设置合适的抓取间隔尤为重要。如果间隔时间过长,可能会错过一些短暂出现的性能问题或临时性错误;而如果间隔时间过短,则可能会导致收集请求过多,从而使系统负担过重,甚至产生过多的网络流量。
targets列出了那些公开Prometheus指标的具体端点。当需要从多个服务中抓取数据时,可以添加多个目标地址。
最后,job_name是一个标识符,它有助于将收集到的指标进行逻辑分类,这样在它们被传输到后端系统后,就更容易进行管理和分析了。

2. 转换 Prometheus 直方图
在获取到这些指标数据后,下一步就是对它们进行转换。Prometheus 将直方图以多种时间序列的形式呈现出来:
_bucket用于显示有多少请求的耗时低于某个特定值。_sum表示所有观测到的耗时值的总和。_count代表观测到的数据条目数量。
payment_transaction_duration_seconds 直方图记录了每笔支付交易所花费的时间。Prometheus 将该数据以 _bucket、_count 和 _sum 这三种形式呈现出来。当 Prometheus 收集器获取到这些指标后,会将其转换为 OpenTelemetry 直方图的数据模型,然后通过 OTLP 导出这些数据,在此过程中所有用于分析交易延迟及计算百分位数的信息都会被保留下来。
如果没有直方图,平均值就无法反映真实的延迟分布情况。例如,如果大多数请求的耗时为 50 毫秒,但有 5% 的请求耗时超过 2 秒,那么 150 毫秒的平均值就会掩盖这一严重的性能问题。而直方图通过记录落入不同延迟区间的数据条目数量,从而呈现出完整的延迟分布情况。
了解这种延迟分布有助于你发现其中的变化,并进一步排查诸如数据库查询缓慢、服务负载过重,或是下游依赖项导致的延迟等问题。
实际的 Prometheus 直方图
以下就是你的实际 /metrics 输出结果示例:
而以下则是 OpenTelemetry 所呈现的直方图形式:
上述两种输出方式实际上表示的是相同的数据——即每笔交易所花费的时间。不过,OpenTelemetry 直方图将这三个独立的 Prometheus 数据序列合并成了一个直方图,其中包含了数据条目数量、总和、具体的延迟区间以及每个区间的数据条目数量等信息。
3. 通过 OTLP 导出指标数据
在获取并处理完这些指标数据后,收集器会使用 OTLP 将它们发送到你的可观测性后端系统。OTLP 输出工具会将处理后的指标数据(包括直方图、计数器等信息)传输到后端系统。
exporters:
otlp:
endpoint: "otlpbackend.example.com:4317"
tls:
insecure: false
endpoint指定了用于接收OTLP指标的后端地址。这个地址通常指向一个中央观测平台,该平台会汇总来自您基础设施中多个服务的指标数据。
tls确保收集器与后端之间的数据传输安全。只有当您有意连接到不使用TLS的终端点时,才应设置insecure: true,例如在某些本地开发环境中。
4. 将各个组件组合起来
我们已经分别了解了管道中的每个组成部分。现在,让我们将它们连接起来,追踪一个指标从应用程序开始,一直传输到后端。
service:
pipelines:
metrics:
receivers: [prometheus]
exporters: [otlp]
这就是我们的payment_transaction_duration_seconds指标所经过的完整路径,从FastAPI应用程序一直传输到观测后端。上面的图表展示了这一流程。下一节将介绍如何实际运行这个流程,并将其连接到SigNoz。
管道流程:
上述架构图显示了一个FastAPI应用程序,它通过//metrics路径暴露指标数据;OpenTelemetry收集器使用Prometheus接收器抓取这些数据,然后对它们进行处理,并通过OTLP将其传输到观测后端。
5. 运行OpenTelemetry收集器
我们将运行整个管道流程,确认交易指标数据能够从应用程序顺利传输到SigNoz。请按照以下步骤操作(下面我会详细说明每个步骤):
配置SigNoz Cloud:设置收集器将使用的终端点和数据导入密钥。
启动FastAPI应用程序:该应用程序会在
/metrics路径上暴露Prometheus指标数据。启动OpenTelemetry收集器:收集器会使用Prometheus接收器开始抓取应用程序的
/metrics端点上的数据。生成测试交易记录:向应用程序发送请求,以创建用于测量交易时长的数据。
验证收集器和后端的运行状态:检查收集器的日志,确认整个管道流程正在正常运行;然后打开SigNoz,确认
payment_transaction_duration_seconds指标数据已经到达。故障排除
5.1 配置SigNoz Cloud
SigNoz提供了用于接收OpenTelemetry收集器所导出指标数据的观测后端。在这个演示中,我们将使用SigNoz Cloud作为观测后端,因此无需在本地进行任何安装操作。
首先,前往signoz.io注册一个免费账户。在SigNoz Cloud控制面板中,选择设置 → 数据采集键选项。该页面会显示您的数据采集URL、所在地区以及数据采集键。
将这些信息添加到项目目录中的.env文件中:
SIGNOZ_ingESTION_KEY=你的实际密钥
SIGNOZ_OTLP_ENDPOINT=ingest..signoz.cloud:443
请将这个数据采集键视为密码,切勿将其提交或公开分享。
在收集器的配置文件中引用这些变量:
exporters:
otlp:
endpoint: "${SIGNOZ_OTLP_ENDPOINT}"
tls:
insecure: false
headers:
signoz-ingestion-key: "${SIGNOZ_ingESTION_KEY}"
接下来,将.env文件添加到.gitignore中,这样这个密钥就不会被提交到代码仓库中:
echo ".env" >> .gitignore
5.2 启动FastAPI应用程序。
在8080端口上启动该应用程序:
uvicorn app.main:app --reload --port 8080
确认应用程序已经成功运行:
curl http://localhost:8080/
现在可以查看Prometheus提供的指标数据了:
curl -Ls http://localhost:8080/metrics
/metrics端点会公开应用程序的Prometheus指标数据,其中就包括收集器会抓取的payment_transaction_duration_seconds直方图。
5.3 启动收集器
在应用程序已经运行且收集器的配置也已完成之后,就可以启动收集器了:
docker compose up --build
请查看收集器的日志,以确认数据采集流程是否正常进行,以及指标数据是否正在被处理。
通过这些步骤,系统会生成payment-api镜像,在共享的telemetry网络中启动两个容器,同时收集器也会立即开始使用Prometheus接收器从应用程序中抓取/metrics端点的数据,并自动读取来自.env文件中的数据采集键和URL信息。
5.4 生成测试交易记录
生成处理时间各不相同的交易记录:
curl -X POST "http://localhost:8080/transactions?delay_ms=50"
curl -X POST "http://localhost:8080/transactions?delay_ms=250"
curl -X POST "http://localhost:8080/transactions?delay_ms=2500"
如果希望在直方图中看到更多数据,可以再生成一些请求记录。
这些请求会生成用于记录交易处理时长的数据,这些数据会被保存到payment_transaction_duration_seconds直方图中。收集器会在下一次数据采集时获取这些更新后的指标值。
5.5 确认后端是否已接收数据
打开SigNoz Cloud,然后搜索以下内容:
payment_transaction_duration_seconds
该指标应该以直方图的形式呈现,其各个分桶的统计数据_bucket、_sum和_count应当被后端系统接收和处理,而不会作为无关的Prometheus指标系列显示出来。
5.6 故障排除
如果指标数据没有正常传输,首先检查日志信息:
docker logs
查找其中是否包含连接错误、认证失败、数据采集失败或配置错误等信息。
同时还需要验证以下内容:
FastAPI应用程序是否正在运行中。
能否正常访问
/metrics路径。收集器是否能够成功连接到该应用程序。
SigNoz的端点地址和数据导入配置是否正确。
收集器是否能够读取到
.env文件中的配置变量。接收器和导出器的名称是否与管道配置相匹配。
如果可能的话,可以使用--dry-run参数在部署前进行验证测试。
结论
Prometheus直方图能够通过展示数据在不同分桶中的分布情况,帮助我们更直观地了解交易处理的延迟情况,而不会将所有数据简化为单一的平均值。
在本教程中,我们展示了如何通过OpenTelemetry Collector将FastAPI应用程序/metrics端点提供的payment_transaction_duration_seconds指标数据导入到SigNoz系统中。
Prometheus的接收器会将_bucket、_count和_sum这些指标系列映射到OpenTelemetry直方图的数据模型中,从而保留交易处理时长的分布信息,便于后端进行分析和处理。
相关文章
如何使用NestJS的观察功能:开发者必备的可观测性实践指南
可观测性并不是一个新出现的问题,NestJS也绝不是第一个试图解决这个问题的生态系统。 但NestJS Observe之所以值得关注,是因为它提出了一个更为具体的问题:当可观测性系统能够理解其所监控的框架时,会发生什么呢? 在了解其实现机制之前,我们首先需要明确这个问题,以及为什么框架的上下文会对此产生重要影响。 可观测性问题 如果你曾经长期开发并维护过服务器应用程序,你肯定遇到过这样的情况:某个API莫名其妙地运行速度变慢了,但你却不知道原因何在。 你检查了日志,却发现没有任何明显的异常。数据库运行正常,也没有任何错误信息;在你的本地机器上,这个接口也能正常工作。 于是你添加了一些日志记录:
阅读全文
苹果手表现在能够估算你的“健康年龄”,但它实际上是在测量什么指标呢?
你的生日告诉你已经活了多少年,但它并不能必然反映你的身体正在以何种速度衰老。 两个同龄人,他们的心血管健康状况、睡眠质量、心脏健康以及新陈代谢水平可能会存在很大差异。换句话说,尽管他们的实际年龄相同,但某些健康指标却可能反映出不同的情况。 “生物年龄”可以说是可穿戴设备领域中的新的“健康评估指标”。苹果新推出的“健康年龄”功能让我开始思考:它究竟是如何测量这一指标的? 与只关注单一指标不同,这一功能综合了长时间收集到的健康数据,从而反映你的某些健康状况相对于实际年龄而言的发展趋势。 但是,仅仅通过手腕上收集的数据以及健康记录,真的能够准确估算出你的身体“老化”到什么程度呢? 为了弄清楚这个问题
阅读全文
如何负责任地使用Lovable产品
过去,开发应用程序往往就像在没有任何说明书的情况下组装家具,而且还会缺少一半的螺丝。如今,像Lovable这样的人工智能工具可以帮助你用简单明了的语言描述自己的需求,从而将一个想法转化为可运行的网页应用。 这确实很令人兴奋——但同时也意味着一种责任。 Lovable能帮助你快速行动、尝试各种想法,并创造出实用的软件。不过,速度绝不能取代周密的思考。由人工智能生成的程序可能会存在安全问题、导致用户使用体验混乱、包含不准确的信息,或者其代码在演示环境中可以正常运行,但在实际使用中却会出故障。 在这份指南中,你将学习到如何在实际使用Lovable的过程中兼顾安全性、隐私性、可访问性以及用户的安全。我
阅读全文
使用OpenTelemetry实现Claude Code的可观测性
像 Claude Code 、 OpenAI Codex 、 Google Antigravity 以及 Cursor 这样的代理编码工具,在日常软件开发中已经变得无处不在。 随着代理系统的不断发展,开发者让这些系统完成的大部分工作都是通过逐个分配子任务来实现的。许多团队也在探索并使用共享的、多租户式的代理基础设施,这种架构的成本不会与某个特定的所有者挂钩。在这种情况下,可观测性就成为了监控基础设施成本的关键因素。 在本指南中,您将了解可观测性的工作原理,然后学习如何启用Claude Code内置的遥测功能,运行后端程序来收集数据,并读取该系统生成的各类指标、日志及追踪信息。这些内容将帮助您更
阅读全文