You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby Prometheus:如何修复大写UUID引发的时间序列基数过高问题

问题背景

我们在Rails应用的config.ru里配置了Prometheus收集器:

use Prometheus::Middleware::Collector

Prometheus的核心原则之一是保持指标低基数,否则会引发性能下降,图表也会失去参考价值。该收集器实现低基数的关键代码如下:

def generate_path(env)
  full_path = [env['SCRIPT_NAME'], env['PATH_INFO']].join

  strip_ids_from_path(full_path)
end

def strip_ids_from_path(path)
  path
    .gsub(%r{/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(?=/|$)}, '/:uuid\\1')
    .gsub(%r{/\d+(?=/|$)}, '/:id\\1')
end

目前这段代码只能处理小写UUID,遇到大写UUID时无法识别,示例如下:

uuid = "f7ec02c0-19b0-4519-8e3e-d8ac4434a389"
irb(main):024:0> strip_ids_from_path("user/#{uuid}")
=> "user/:uuid"
irb(main):025:0> strip_ids_from_path("user/#{uuid.upcase}")
=> "user/F7EC02C0-19B0-4519-8E3E-D8AC4434A389"

我可以复制整个中间件并修改成strip_ids_from_path(full_path.downcase),但这种复制整段代码的修复方式不够优雅。想请教有没有更巧妙的解决方案?能否借助Rails特性来处理?


解决方案

1. 给正则添加不区分大小写修饰符

不需要复制整个中间件,只用class_eval重写特定方法,给UUID匹配正则加上i修饰符,让它同时匹配大小写字母:

Prometheus::Middleware::Collector.class_eval do
  def strip_ids_from_path(path)
    path
      .gsub(%r{/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(?=/|$)i}, '/:uuid\\1')
      .gsub(%r{/\d+(?=/|$)}, '/:id\\1')
  end
end

这种方式侵入性低,只修改核心匹配逻辑。

2. 利用Rails路由识别(推荐)

如果你的Rails应用已经定义了对应路由(比如GET /users/:uuid),可以直接复用Rails的路由系统来生成标准化路径,完全不用自己处理UUID格式:

Prometheus::Middleware::Collector.class_eval do
  def generate_path(env)
    request = ActionDispatch::Request.new(env)
    route = Rails.application.routes.recognize_path(request.path)
    # 生成标准化的路由路径模板
    Rails.application.routes.url_helpers.polymorphic_path(route.except(:controller, :action), format: nil)
  rescue ActionController::RoutingError
    # 无法识别的路由回退到原逻辑
    super
  end
end

这种方式不仅能处理大小写UUID,还能自动适配其他动态参数,完全贴合Rails生态。

3. 轻量修改:调用前转小写

如果不想改动正则,也可以只重写generate_path方法,在调用原处理方法前把路径转小写:

Prometheus::Middleware::Collector.class_eval do
  def generate_path(env)
    full_path = [env['SCRIPT_NAME'], env['PATH_INFO']].join
    strip_ids_from_path(full_path.downcase)
  end
end

这种方式改动最小,只修改路径处理的入口逻辑,不影响原方法的其他功能。


内容的提问来源于stack exchange,提问作者David Michael Gang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 20:55:58