Ruby on Rails 接入 Prometheus 监控
Rails 应用接入 Prometheus:prometheus-client gem、Rack 中间件暴露 /metrics、Counter/Gauge/Histogram 埋点、Puma 多进程模式的数据聚合问题与解决方案。
Rails 应用接入 Prometheus 用官方 prometheus-client gem。和 PHP 类似,Ruby 的多进程服务器(Puma workers)带来指标聚合问题——本文把正确姿势一次讲清。
安装
# Gemfile
gem 'prometheus-client'
bundle install
暴露 /metrics 端点
# config.ru
require 'prometheus/middleware/exporter'
use Prometheus::Middleware::Exporter # 在 /metrics 暴露指标
埋点三种指标
require 'prometheus/client'
registry = Prometheus::Client.registry
# Counter:请求总数
requests = registry.counter(:http_requests_total,
docstring: 'Total HTTP requests', labels: [:method, :path, :status])
requests.increment(labels: { method: 'GET', path: '/users', status: 200 })
# Gauge:瞬时值(活跃连接)
active = registry.gauge(:http_active_requests, docstring: 'Active requests')
active.increment
# ... 处理完
active.decrement
# Histogram:延迟分布
latency = registry.histogram(:http_request_duration_seconds,
docstring: 'Request duration', labels: [:path],
buckets: [0.01, 0.05, 0.1, 0.5, 1, 5])
latency.observe(0.23, labels: { path: '/users' })
Rack 中间件统一采集
class MetricsMiddleware
def initialize(app)
@app = app
@registry = Prometheus::Client.registry
@requests = @registry.counter(:http_requests_total, docstring: '...', labels: [:method, :path, :status])
@latency = @registry.histogram(:http_request_duration_seconds, docstring: '...', labels: [:path])
end
def call(env)
start = Time.now
status, headers, body = @app.call(env)
path = route_template(env) # 用路由模板!
@requests.increment(labels: { method: env['REQUEST_METHOD'], path: path, status: status })
@latency.observe(Time.now - start, labels: { path: path })
[status, headers, body]
end
end
多进程模式:Puma 的坑
Puma 以多 worker 进程运行时,每个 worker 有自己的内存指标注册表——/metrics 被哪个 worker 响应,就只能看到那个 worker 的数据,指标残缺不全。
解法:
- 官方多进程模式:设置
PROMETHEUS_MULTIPROC_DIR环境变量,客户端库用文件在 worker 间聚合(新版prometheus-client的 data store 机制); - 或换方案:用
prometheus_exportergem(独立进程聚合指标,Ruby 社区更主流的选择)。
观测云对照
Rails 应用接入观测云 APM可自动获得请求速率、错误率、延迟分解(含 ActiveRecord 慢查询定位),免手写埋点;自定义业务指标经 DataKit 抓取汇聚后,与链路数据在同一视图联动——定位"某个接口为什么慢"从翻日志变成看火焰图。
常见问题(FAQ)
Q:Sidekiq 任务怎么监控?
A:在 worker 执行器里埋点(处理数、失败数、耗时),队列积压用 Sidekiq 自己的 API 定期采样成 Gauge。
Q:Rails 7 的 importmap/esbuild 影响吗?
A:不影响——指标是服务端的事,与前端构建方式无关。
Q:histogram 桶怎么设计?
A:围绕你的 SLO 设:如 SLO 是 300ms,桶设 [0.05, 0.1, 0.3, 0.5, 1, 3],SLO 阈值附近密度最高。