资讯详情

使用 Grafana Tempo 与 Pyroscope 实现 Trace 到 Profile 关联分析:tracing/tempo 示例全解析

📅 2026/9/15 15:48:08 | 华诺云谱 👁 阅读
使用 Grafana Tempo 与 Pyroscope 实现 Trace 到 Profile 关联分析:tracing/tempo 示例全解析
使用 Grafana Tempo 与 Pyroscope 实现 Trace 到 Profile 关联分析tracing/tempo 示例全解析【免费下载链接】pyroscopeContinuous Profiling Platform. Debug performance issues down to a single line of code项目地址: https://gitcode.com/GitHub_Trending/py/pyroscope本篇文章基于仓库examples/tracing/tempo示例系统讲解如何在 Grafana 中打通「分布式追踪Tempo」与「持续剖析Pyroscope」两条观测链路从一条 Trace 的某个 Span 一键跳转到对应时间段内的 CPU Profile 火焰图定位性能问题到具体代码行。读完本文你将掌握示例的完整架构组成、本地一键启动方式、Grafana Tempo 数据源trace-to-profiles的配置原理与参数含义以及底层埋点OTel Pyroscope SDK是如何把 Span 与 Profile 关联起来的。示例概览一套可本地运行的 Trace ↔ Profile 联动演示examples/tracing/tempo/README.md描述的是一个用 Docker Compose 编排的端到端演示环境它由四类组件构成Ride share 演示应用rideshare模拟打车场景的多语言业务服务同时产生链路追踪与剖析数据Tempo链路追踪后端负责接收、存储和查询 TracePyroscope持续剖析平台负责接收、存储和查询 ProfileGrafana统一可视化入口预置好 Tempo 与 Pyroscope 数据源。rideshare应用产生的 Trace 和 Profiling 数据都会汇入 Grafana且 Pyroscope、Tempo 数据源由 Grafana provisioning 机制自动配置无需手工录入。整个编排定义在 docker-compose.yml 中下面先拆解它的服务组成。docker-compose 服务拓扑examples/tracing/tempo/docker-compose.yml 中定义了 8 个服务其中应用侧按语言/区域拆分出 4 个实例外加 1 个负载生成器服务说明关键配置rideshare-go-ap-southGo 版 rideshare区域 ap-south暴露 5000 端口PYROSCOPE_SERVER_ADDRESShttp://pyroscope:4040OTLP_URLtempo:4318rideshare-go-eu-northGo 版 rideshare区域 eu-north复用基础环境变量仅覆盖REGIONrideshare-dotnet-eu-west.NET 版 rideshare区域 eu-west走 OTLP gRPCtempo:4317OTEL_RESOURCE_ATTRIBUTES设置host.namePYROSCOPE_LABELS设置hostnamerideshare-python-eu-eastPython 版 rideshare区域 us-east同样走 OTLP gRPC设置PYROSCOPE_LABELS: hostname...load-generator负载生成器依次向 4 个 rideshare 实例的 5000 端口发起请求制造持续流量grafana可视化平台预装grafana-pyroscope-app插件开启traceToProfiles、tracesEmbeddedFlameGraph特性开关tempo链路追踪后端镜像grafana/tempo:2.10.8开放 OTLP、Jaeger、Zipkin 等接收端口pyroscope持续剖析后端镜像grafana/pyroscope:latest暴露 4040 端口几点值得注意的编排细节应用实例的「身份标签」是关联链路与剖析数据的关键。例如rideshare-dotnet-eu-west通过OTEL_RESOURCE_ATTRIBUTES把host.namerideshare-dotnet-eu-west写入 Span 资源属性同时通过PYROSCOPE_LABELS把hostnamerideshare-dotnet-eu-west写入剖析标签——这正是后文「Tempo 数据源 tags 配置」能生效的前提README 中host.name → hostname的映射即源于此。Grafana 通过环境变量开启了两个关键特性开关GF_FEATURE_TOGGLES_ENABLEtraceToProfiles tracesEmbeddedFlameGraph。前者启用「从 Trace 跳转到 Profile」后者允许在 Trace 视图中直接内嵌渲染火焰图。服务配置统一由模板生成grafana、tempo、pyroscope 三个服务的配置均标注为「由examples/_templates/模板生成修改后需执行make examples/sync-templates」说明该示例与仓库其他示例共用一套模板保持配置一致。Tempo 与 Pyroscope 的服务端配置Tempo 的配置位于 examples/tracing/tempo/tempo/tempo.yml它开启了多种接收协议distributor receivers同时启用 Jaegerthrift_http / grpc / thrift_binary / thrift_compact、Zipkin 与 OTLPHTTP0.0.0.0:4318、gRPC0.0.0.0:4317注释中特别提醒生产环境应只按需开启实际使用的 receiverquery_frontend设置了搜索与按 TraceID 查询的 SLO5s 延迟目标storage使用local后端WAL 与 block 分别落在/tmp/tempo/wal与/tmp/tempo/blocks适合本地演示。Pyroscope 的配置位于 examples/tracing/tempo/pyroscope/pyroscope.yml只包含两个关键项tracing: enabled: true profiling_enabled: true pyroscopedb: max_block_duration: 5m它表明Pyroscope 自身也被插桩tracing.enabled开启 Pyroscope 的内部链路追踪profiling_enabled开启对 Pyroscope 自身运行时的剖析采集README 中明确说明 pyroscope 自身使用 OpenTelemetry 与otel-profiling-go做剖析集成pyroscopedb.max_block_duration: 5m控制存储 block 的最大时间跨度。快速启动两条命令拉起整套环境README 给出的启动方式极为简洁分两步# Pull latest pyroscope and grafana images: docker pull grafana/pyroscope:latest docker pull grafana/grafana:latest docker-compose up操作说明先拉取最新版 Pyroscope 与 Grafana 镜像Tempo 镜像已由 compose 文件锁定为grafana/tempo:2.10.8在 examples/tracing/tempo 目录下执行docker-compose up新版本 Docker 也可使用docker compose up即可启动全部服务。启动后访问 Grafana 的Explore 页面即可在 Tempo 数据源中查询ride-sharing-app服务的 Trace。README 给出了一个可直接粘贴到浏览器地址栏的深链其核心查询参数是Tempo 数据源datasourcetempo、traceqlSearch查询类型、service.name ride-sharing-app资源过滤条件以及now-6h到now的时间范围。选中一条 Trace 后点击带有 Profile 关联标记的 SpanREADME 配图中展示Span 右侧出现「View profile」类入口即可从追踪视图直接跳转到 Pyroscope 的火焰图形成「Trace 定位请求 → Profile 定位 CPU 热点」的完整排查闭环。README 的截图演示了从 Tempo 的 Span 详情进入 Pyroscope CPU 火焰图的界面效果。关联原理Span 与 Profile 是如何绑定到一起的README 对该示例的关联机制做了三点关键说明这是理解整套方案的核心默认只有根 Span 被标记关联root span即本地创建的第一个 Span。这类 Span 会显示link链接图标并且其属性中带有pyroscope.profile.id值对应当前 Span 的 Span IDpyroscope.profile.id属性存在 ≠ Span 一定有 Profile。由于采样是按固定时间间隔进行的当某个 Span 实际消耗的 CPU 时间**小于采样间隔10ms**时可能采集不到任何堆栈样本因而没有可用的 Profile 数据在 Explore 中从 Trace 跳转 Profile 依赖 Tempo 数据源的trace-to-profiles配置详见下一节。底层实现可以结合样例应用源码印证。在 examples/language-sdk-instrumentation/golang-push/rideshare/main.go 中应用把 OTel TracerProvider 包装为 Pyroscope 提供的otelpyroscope.NewTracerProvider(tp)// Set the Tracer Provider and the W3C Trace Context propagator as globals. // We wrap the tracer provider to also annotate goroutines with Span ID so // that pprof would add corresponding labels to profiling samples. otel.SetTracerProvider(otelpyroscope.NewTracerProvider(tp))从注释可以确认关联机制该包装器会在剖析采样时用当前 Span ID 标注 goroutine使 pprof 采集到的剖析样本携带对应的 Span 标签Pyroscope 侧再以这些标签为索引建立 Span → Profile 的映射最终以pyroscope.profile.id属性的形式呈现在 Span 上。而剖析数据的产生来自 rideshare.go 中通过pyroscope-goSDK 启动的 Profiler应用名取自PYROSCOPE_APPLICATION_NAME默认ride-sharing-app上报地址取自PYROSCOPE_SERVER_ADDRESS默认http://localhost:4040。Grafana Tempo 数据源配置trace-to-profiles 详解要让「Trace 跳转 Profile」真正可用必须对 Tempo 数据源做如下配置README 列出的四个要点Profile 数据源Data source of the profiling data指定保存剖析数据的数据源本示例为 Pyroscope查询中使用的标签Tags to use in the query指定把 Span 上的哪些标签映射为 Pyroscope 查询标签Profile 类型Profile type目前只有 CPU time 类型的 Profile 得到完整支持查询覆盖Query override是否使用自定义查询替代默认生成的查询。这些配置在示例的 Grafana 预置文件中有完整落地。见 examples/tracing/tempo/grafana-provisioning/datasources/tempo.yml--- apiVersion: 1 datasources: - name: Tempo type: tempo access: proxy orgId: 1 url: http://tempo:3200 basicAuth: false isDefault: true version: 1 editable: false apiVersion: 1 uid: tempo jsonData: httpMethod: GET serviceMap: datasourceUid: prometheus tracesToProfiles: customQuery: false datasourceUid: pyroscope profileTypeId: process_cpu:cpu:nanoseconds:cpu:nanoseconds tags: - key: service.name value: service_name各字段含义如下字段示例值作用tracesToProfiles.datasourceUidpyroscopeProfile 数据源 UID指向同目录 pyroscope.yml 中定义的grafana-pyroscope-datasourcetracesToProfiles.profileTypeIdprocess_cpu:cpu:nanoseconds:cpu:nanoseconds要跳转的 Profile 类型对应CPU 时间剖析印证了 README「只有 CPU time 完全支持」的说明tracesToProfiles.customQueryfalse关闭自定义查询使用 Grafana 自动生成的默认查询对应 README 的「Query override」选项tracesToProfiles.tagsservice.name → service_name标签映射列表将 Span 上的标签映射为 Pyroscope 查询标签仓库中还有一份等价变体 examples/tracing/tempo/grafana/provisioning/datasources/datasources.yml它把标签映射配置为host.name → hostname并同时注册了 Tempo 与 Pyroscope 两个数据源Pyroscope 指向http://pyroscope:4040。这与 README 中「配置host.name标签用于 Pyroscope 查询中的hostname标签」的表述一致。标签Tags配置可选但强烈建议README 强调标签配置是可选的但强烈建议配置因为它直接决定查询性能。示例中的做法是在 Tempo 侧配置host.name标签映射为 Pyroscope 查询中的hostname标签效果是跳转查询会把数据集限定在特定主机上从而让查询始终快速返回restricts the data set for lookup to a specific host。为什么能加速结合 docker-compose.yml 可以看到每个 rideshare 实例的hostname与PYROSCOPE_LABELS都被设置为各自唯一的服务名如rideshare-dotnet-eu-west。当 Tempo 数据源用host.namerideshare-dotnet-eu-west去查询 Pyroscope 时Pyroscope 只需在带hostnamerideshare-dotnet-eu-west标签的样本集合中查找缩小了扫描范围。同时 README 给出一条必须遵守的前置条件你配置的标签必须真实存在于 Span 的属性attributes或资源resources中否则 Trace 到 Profile 的跳转链接不会出现。也就是说标签的 key 必须与 Span 上的属性/资源 key 一致例如host.name标签的 value 必须与 Pyroscope 侧的标签值对应例如hostname标签值两侧命名需要按映射关系对齐。在 .NET 实例中可以看到这种对齐的落地方式OTEL_RESOURCE_ATTRIBUTES: host.namerideshare-dotnet-eu-westSpan 资源属性PYROSCOPE_LABELS: hostnamerideshare-dotnet-eu-west剖析标签。若两者不一致或 Span 上缺少该属性Grafana 无法生成有效的关联查询。埋点侧实现多语言 OTel 集成的样板README 的「Instrumentation」一节说明了示例的插桩方案rideshare演示应用使用 OpenTelemetry 埋点Go 侧使用Go OTel integrationotel-profiling-goJava 侧使用Java OTel integrationotel-profiling-javapyroscope自身同样使用 OpenTelemetry 与otel-profiling-go做剖析集成。仓库中对应的多语言样例位于 examples/language-sdk-instrumentation/golang-push/rideshare以及examples/language-sdk-instrumentation下的dotnet、java、python、ruby、nodejs等目录可对照参考。以 Go 样例为例其 OTel 初始化链路在 main.go 的setupOTEL中完成分别构建 TracerProvider、LoggerProvider、MeterProvider并把包装后的 TracerProvider 设置为全局HTTP 路由通过otelhttp.NewHandler包装如BikeHandler、CarHandler使每个请求自动生成对应 Span。rideshare.go中的ReadConfig()则集中读取环境变量包括PYROSCOPE_APPLICATION_NAME剖析应用名默认ride-sharing-appPYROSCOPE_SERVER_ADDRESSPyroscope 上报地址默认http://localhost:4040PYROSCOPE_BASIC_AUTH_USER/PASSWORD连接带认证的 Pyroscope 服务如 Grafana Cloud时使用OTLP_URL/OTLP_INSECUREOTLP 上报地址与是否使用非加密连接compose 中指向tempo:4318REGION、hostname等被写入剖析标签Tags的键值。Profiler()函数rideshare.go用这些配置调用pyroscope.Start(config)启动持续剖析与 OTel Trace 上报并行工作二者在 Pyroscope/Tempo 后端汇合后即可被 Grafana 关联。使用限制与注意事项综合 README 与仓库配置使用该方案时有几点需要牢记Profile 类型限制目前trace-to-profiles只完整支持 CPU time 剖析process_cpu:cpu:nanoseconds:cpu:nanoseconds其他 profile 类型的关联能力有限短 Span 可能无 Profile由于采样间隔为 10msCPU 时间低于采样间隔的 Span 可能没有堆栈样本pyroscope.profile.id属性存在并不代表一定有可跳转的 Profile默认仅根 Span 标记示例默认只对根 Span 建立关联并显示链接图标标签必须存在配置的 tags 必须出现在 Span 的属性或资源中否则跳转链接不会出现标签映射应尽量选择区分度高的属性如host.name以缩小 Pyroscope 查询范围、保证查询性能生产环境按需裁剪Tempo 配置中默认开启了 Jaeger/Zipkin/OTLP 全部接收协议生产部署应只保留实际需要的协议与端口。小结examples/tracing/tempo示例展示了一条完整的「分布式追踪 持续剖析」联动链路多语言 rideshare 应用通过 OTel 与 Pyroscope SDK 同时产生 Trace 和 ProfileTempo 与 Pyroscope 分别负责两类数据的存储与查询Grafana 借助 Tempo 数据源的trace-to-profiles配置Profile 数据源、标签映射、Profile 类型、查询覆盖四个要素把二者关联起来让开发者从一条 Trace 的 Span 一键进入对应的 CPU 火焰图。想要在自有环境中复刻这一能力核心动作就是为应用接入 OTel 与 Pyroscope SDK 并保证标签对齐然后按本文所述配置 Tempo 数据源即可。延伸阅读同一仓库的 examples/tracing 目录下还提供了dotnet、golang-push、java、java-wall、python、ruby等多个语言的同主题示例可对照学习不同语言生态下的 Trace/Profile 关联接入方式。【免费下载链接】pyroscopeContinuous Profiling Platform. Debug performance issues down to a single line of code项目地址: https://gitcode.com/GitHub_Trending/py/pyroscope创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。