Ruby 应用接入 Pyroscope 持续性能剖析:simple 示例从零到火焰图
【免费下载链接】pyroscopeContinuous Profiling Platform. Debug performance issues down to a single line of code项目地址: https://gitcode.com/GitHub_Trending/py/pyroscope
Pyroscope 是一个持续性能剖析平台(Continuous Profiling Platform),可把性能问题定位到一行代码。本指南以仓库中的examples/language-sdk-instrumentation/ruby/simple示例为蓝本,完整讲解如何用官方 Ruby SDK(pyroscopegem)为 Ruby 应用接入 Pyroscope:包括环境搭建、SDK 配置、静态与动态标签(tag)注入,以及如何在 Grafana 中查看火焰图。读完本文,你将能够在本地一键跑起一个可观测的 Ruby 剖析示例,并理解其背后的数据通路。
一、示例概览:一个最小可运行的 Ruby 剖析项目
simple示例是整个 Ruby 示例家族中最小的一个,它的目录结构如下:
examples/language-sdk-instrumentation/ruby/simple/ ├── Dockerfile # 应用镜像:Ruby 3.3.9 + pyroscope gem ├── Gemfile # 声明 pyroscope gem 版本 ├── Gemfile.lock # 锁定的依赖(含各平台二进制) ├── main.rb # 被剖析的 Ruby 应用本体 ├── docker-compose.yml # pyroscope + app + grafana 三服务编排 ├── grafana-provisioning/ │ └── datasources/ │ └── pyroscope.yml # Grafana 数据源自动配置 └── README.md # 本示例的启动说明与同目录下的rideshare(模拟网约车公司多服务、多区域场景)和rideshare_rails(Rails 版本)相比,simple只保留了一个死循环 CPU 负载程序main.rb,用于演示最基础的接入与打标签方式,适合作为学习 Pyroscope Ruby SDK 的起点。
二、快速启动:三条命令跑起完整链路
根据 simple/README.md 的说明,启动示例共分两步:
# 1. 拉取最新的 pyroscope 与 grafana 镜像: docker pull grafana/pyroscope:latest docker pull grafana/grafana:latest # 2. 构建并启动示例项目: docker compose up --build # 3. 如需重置数据库(重新开始收集数据): docker compose down启动后,docker compose up --build会依次拉起三个服务(见 simple/docker-compose.yml):
pyroscope:Pyroscope 服务端,暴露4040:4040端口,负责接收剖析数据并提供查询 API;app:通过build: .基于本地 Dockerfile 构建的 Ruby 应用,持续产生 CPU 负载并上报剖析数据;grafana:Grafana 前端,暴露3000:3000,已预装 Pyroscope App 插件。
注意:
simple/docker-compose.yml与grafana-provisioning/datasources/pyroscope.yml均由仓库模板生成(文件头注释标明来源为examples/_templates/下的模板,通过make examples/sync-templates同步),如需修改需改模板而非直接编辑生成文件。
在 Grafana 中查看火焰图
服务全部就绪后,浏览器打开以下链接即可直接进入火焰图探索页面:
http://localhost:3000/a/grafana-pyroscope-app/explore?explorationType=flame-graph&var-serviceName=test.ruby.app&var-profileMetricId=process_cpu:cpu:nanoseconds:cpu:nanoseconds该链接预置了两个关键查询参数:
var-serviceName=test.ruby.app:对应main.rb中config.application_name设置的"test.ruby.app";var-profileMetricId=process_cpu:cpu:nanoseconds:cpu:nanoseconds:选择process_cpu这一 CPU 采样指标(nanoseconds 计量单位)。
由于 Grafana 容器开启了匿名登录(GF_AUTH_ANONYMOUS_ENABLED=true且禁用登录表单),打开即用,无需账号。
三、被剖析的应用本体:main.rb 源码逐行解读
simple/main.rb 完整展示了 Pyroscope Ruby SDK 的两种核心用法:初始化配置与动态打标签。
3.1 SDK 初始化配置
require "pyroscope" Pyroscope.configure do |config| config.application_name = "test.ruby.app" config.server_address = "http://pyroscope:4040/" config.tags = { :region => "us-east", :hostname => ENV["HOSTNAME"] } end四个配置项的含义:
| 配置项 | 取值示例 | 说明 |
|---|---|---|
application_name | "test.ruby.app" | 应用名,在 Grafana 中作为服务标识(service name),对应火焰图查询参数var-serviceName |
server_address | "http://pyroscope:4040/" | Pyroscope 服务端地址;在 Docker Compose 网络内直接使用服务名pyroscope,宿主机访问则用localhost:4040 |
tags(静态标签) | region: "us-east"、hostname: ENV["HOSTNAME"] | 在初始化阶段固定的标签,如地域、主机名;这里 hostname 取自容器环境变量,可动态注入 |
config.tags的键 | Ruby Symbol / String 均可 | 示例同时展示了:regionSymbol 键与"function"字符串键两种写法 |
3.2 静态标签与动态标签
main.rb演示了 Pyroscope 最核心的能力——标签(tag):
- 静态标签:在
Pyroscope.configure的config.tags中声明,生命周期与应用相同,适合标注地域、环境、主机等相对固定的维度; - 动态标签:在函数内部用
Pyroscope.tag_wrapper包裹,随代码块进入/退出而生效/失效。
3.3 用 tag_wrapper 动态区分热点函数
def fast_function Pyroscope.tag_wrapper({ "function" => "fast" }) do work(20000) end end def slow_function Pyroscope.tag_wrapper({ "function" => "slow" }) do work(80000) end endtag_wrapper的行为(可对照 ruby/README.md 中的find_nearest_vehicle示例理解):
- 进入代码块前,向当前剖析上下文追加标签
{ "function" => "fast" }(或"slow"); - 执行代码块内的业务逻辑(这里是
work(n)死循环 CPU 消耗); - 代码块结束,SDK 在幕后自动移除该标签,避免污染后续调用。
主循环则交替调用快慢函数,制造两个耗时差异明显的热点:
while true fast_function # work(20000),CPU 消耗较低 slow_function # work(80000),CPU 消耗约为 fast 的 4 倍 end这样在火焰图中就能直观看到work在不同标签下的 CPU 占比差异,这正是 tag 在性能对比中的典型用法:把同一函数的不同调用路径(如不同端点、不同业务分支)拆开对比。
四、Dockerfile 与依赖:SDK 版本与运行环境
simple/Dockerfile 揭示了示例的运行环境细节:
FROM ruby:3.3.9 WORKDIR /usr/src/app RUN adduser --disabled-password --gecos --quiet pyroscope USER pyroscope COPY --from=pyroscope/pyroscope:latest /usr/bin/pyroscope /usr/bin/pyroscope COPY --chown=pyroscope main.rb ./main.rb COPY --chown=pyroscope Gemfile ./Gemfile COPY --chown=pyroscope Gemfile.lock ./Gemfile.lock ENV PYROSCOPE_APPLICATION_NAME=simple.ruby.app ENV PYROSCOPE_SERVER_ADDRESS=http://pyroscope:4040/ ENV PYROSCOPE_LOG_LEVEL=debug RUN bundle install CMD ["ruby", "main.rb"]几个值得注意的点:
- 基础镜像为
ruby:3.3.9,以非 root 用户pyroscope运行; - 通过
COPY --from=pyroscope/pyroscope:latest从 Pyroscope 官方镜像中拷入 CLI 二进制(示例未直接调用,但保留了这一能力); - 设置了三个环境变量:
PYROSCOPE_APPLICATION_NAME、PYROSCOPE_SERVER_ADDRESS、PYROSCOPE_LOG_LEVEL=debug(后两者会被main.rb中的显式配置覆盖或补充,其中日志级别有助于排查上报问题); CMD ["ruby", "main.rb"]启动主程序。
依赖声明见 simple/Gemfile:gem 'pyroscope', '= 1.0.7',版本被精确锁定。由 Gemfile.lock 可见,pyroscopegem 通过ffi依赖绑定各平台原生二进制(aarch64-linux、arm64-darwin、x86_64-linux等),即该 gem 在安装时会拉取对应平台的剖析采集器,这也是它能做到轻量采集的底层机制。
五、Grafana 数据源自动配置
Grafana 容器通过挂载卷./grafana-provisioning:/etc/grafana/provisioning实现开箱即用的数据源配置,核心文件为 simple/grafana-provisioning/datasources/pyroscope.yml:
apiVersion: 1 datasources: - uid: pyroscope type: grafana-pyroscope-datasource name: Pyroscope url: http://pyroscope:4040 jsonData: keepCookies: [pyroscope_git_session] ## 若配合 Grafana Cloud 使用,可取消注释: # basicAuth: true # basicAuthUser: '123456' # secureJsonData: # basicAuthPassword: PASSWORD要点:
- 数据源类型为
grafana-pyroscope-datasource,指向容器网络内的http://pyroscope:4040; - 文件中的注释给出了接入 Grafana Cloud 时的基本认证(basicAuth)配置范式;
- 该文件同样由模板生成(来源为
examples/_templates/下的 grafana 模板)。
而在 simple/docker-compose.yml 中,Grafana 服务还通过环境变量预装插件、开启匿名访问并启用与链路相关的功能开关:
GF_PLUGINS_PREINSTALL_SYNC=grafana-pyroscope-app GF_AUTH_ANONYMOUS_ENABLED=true GF_AUTH_ANONYMOUS_ORG_ROLE=Admin GF_AUTH_DISABLE_LOGIN_FORM=true GF_FEATURE_TOGGLES_ENABLE=traceToProfiles tracesEmbeddedFlameGraph六、从 simple 出发:标签能力与进阶示例
simple只展示了function这一个动态标签。标签能力在更大的示例中体现得更充分:同目录的 ruby/README.md 记录了 rideshare 示例的做法——用静态标签标注服务器所在region,用Pyroscope.tag_wrapper动态标注端点(vehicle),从而在火焰图中按维度切分数据,定位"到底是哪个端点慢、还是哪个区域慢"。
仓库中还提供了两个进阶示例,可直接对照学习:
- rideshare:模拟三个区域、三个端点的网约车服务,并附带
load-generator.py制造压测流量,火焰图中可直接观察不同函数 CPU 占比与标签过滤效果; - rideshare_rails:同一场景的 Rails(含
application_controller.rb、bike_controller.rb等)实现,其 config/initializers/pyroscope.rb 展示了在 Rails 初始化器中接入 SDK 的方式,更贴近真实生产项目。
七、常见问题与排查思路
- 火焰图迟迟不更新:Pyroscope 按采样间隔聚合数据,一般等待 20~30 秒后刷新页面即可看到(该节奏在 ruby/README.md 中有说明);
- 看不到
test.ruby.app服务:确认main.rb的application_name与 Grafana 链接中的var-serviceName一致,且容器日志中无上报错误(Dockerfile 中设置了PYROSCOPE_LOG_LEVEL=debug,可用docker compose logs app查看); - 需要清空数据重来:执行
docker compose down后重新docker compose up --build即可(示例未挂载持久化卷,容器销毁即数据重置); - 服务地址不通:容器内互访必须使用 Compose 服务名
pyroscope:4040,宿主机或外部访问才使用localhost:4040。
至此,你已经掌握了一条完整的 Ruby 持续剖析链路:main.rb采集 CPU 采样并通过 gem 上报到pyroscope:4040,Grafana 通过预置数据源读取并渲染为火焰图,而标签机制则让你能够按任意业务维度(区域、端点、函数分支)拆解性能数据,快速定位性能瓶颈。
【免费下载链接】pyroscopeContinuous Profiling Platform. Debug performance issues down to a single line of code项目地址: https://gitcode.com/GitHub_Trending/py/pyroscope
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考