TL;DR

  • 使用 middleware
官网

https://github.com/fastly/sidekiq-prometheus

环境搭建

在 [[sidekiq环境]] 的环境基础上,加上sidekiq_prometheus

require "sidekiq"
require "sidekiq_prometheus"

class PlainOldRuby
  include Sidekiq::Job

  def perform(how_hard = "super hard", how_long = 1)
    sleep how_long
    puts "Workin' #{how_hard}"
  end
end

if $0 != 'irb'
  SidekiqPrometheus.setup
end

启动sidekiq客户端

bundle exec irb -r ./por.rb
irb(main):001:0> PlainOldRuby.perform_async "like a dog", 3
=> "2d9f35212b39a8bef935370b"

启动sidekiq服务端和/metrics接口

bundle exec sidekiq -r ./por.rb

访问 http://localhost:9359/metrics

源码

调用SidekiqPrometheus.setup会干三件事:注册指标、收集指标、暴露指标

注册指标

调用

# sidekiq_prometheus-1.8.1/lib/sidekiq_prometheus.rb
def setup
  # ...
  SidekiqPrometheus::Metrics.register_sidekiq_job_metrics
  SidekiqPrometheus::Metrics.register_sidekiq_gc_metric if gc_metrics_enabled?
  SidekiqPrometheus::Metrics.register_sidekiq_worker_gc_metrics if gc_metrics_enabled? && periodic_metrics_enabled?
  SidekiqPrometheus::Metrics.register_sidekiq_global_metrics if global_metrics_enabled? && periodic_metrics_enabled?
  register_custom_metrics
  # ...
end

module SidekiqPrometheus::Metrics
  SIDEKIQ_GLOBAL_METRICS = [
    { name:      :sidekiq_workers_size,
      type:      :gauge,
      docstring: 'Total number of workers processing jobs', },
    # ...
  ]
  SIDEKIQ_JOB_METRICS = [
    { name:      :sidekiq_job_count,
      type:      :counter,
      docstring: 'Count of Sidekiq jobs',
      labels:    JOB_LABELS, },
    # ...
  ]

  def register_sidekiq_job_metrics
    register_metrics SIDEKIQ_JOB_METRICS
  end

  def register_sidekiq_global_metrics
    register_metrics SIDEKIQ_GLOBAL_METRICS
  end

  def register(type:, name:, docstring:, labels: [], preset_labels: {}, buckets: nil)
    # ...
    registry.send(type, name.to_sym, **options)
  end
end

调用SidekiqPrometheus.setup

[[prometheus的client_ruby源码]]

module SidekiqPrometheus
  module_function

  def setup
    # ...
    sidekiq_setup
    # ...
  end

  def sidekiq_setup
    Sidekiq.configure_server do |config|
      # ...
      if metrics_server_enabled?
        config.on(:startup)  { SidekiqPrometheus.metrics_server }
        config.on(:shutdown) { SidekiqPrometheus.metrics_server.kill }
      end
    end
  end

  def metrics_server
    opts = {
      Port: SidekiqPrometheus.metrics_port,
      Host: SidekiqPrometheus.metrics_host,
    }

    # ...

    @_metrics_server ||= Thread.new do
      Rack::Handler::WEBrick.run(
        Rack::Builder.new {
          use Prometheus::Middleware::Exporter, registry: SidekiqPrometheus.registry
          run ->(_) { [301, { 'Location' => '/metrics' }, []] }
        },
        **opts
      )
    end
  end
end