diff --git a/lib/prometheus_exporter/server/sidekiq_process_collector.rb b/lib/prometheus_exporter/server/sidekiq_process_collector.rb index 388eb9f..504be4b 100644 --- a/lib/prometheus_exporter/server/sidekiq_process_collector.rb +++ b/lib/prometheus_exporter/server/sidekiq_process_collector.rb @@ -24,9 +24,9 @@ def metrics SIDEKIQ_PROCESS_GAUGES.each_key { |name| gauges[name]&.reset! } sidekiq_metrics.map do |metric| - labels = metric.fetch("labels", {}) + labels = (metric["custom_labels"] || {}).merge(metric["process"]["labels"] || {}) SIDEKIQ_PROCESS_GAUGES.map do |name, help| - if (value = metric[name]) + if (value = metric["process"][name]) gauge = gauges[name] ||= PrometheusExporter::Metric::Gauge.new( "sidekiq_process_#{name}", @@ -41,7 +41,7 @@ def metrics end def collect(object) - @sidekiq_metrics << object["process"] + @sidekiq_metrics << object end end end diff --git a/lib/prometheus_exporter/server/sidekiq_stats_collector.rb b/lib/prometheus_exporter/server/sidekiq_stats_collector.rb index 0587772..07c3b88 100644 --- a/lib/prometheus_exporter/server/sidekiq_stats_collector.rb +++ b/lib/prometheus_exporter/server/sidekiq_stats_collector.rb @@ -30,11 +30,12 @@ def metrics SIDEKIQ_STATS_GAUGES.each_key { |name| gauges[name]&.reset! } sidekiq_metrics.map do |metric| + labels = metric.fetch("custom_labels", {}) SIDEKIQ_STATS_GAUGES.map do |name, help| if (value = metric["stats"][name]) gauge = gauges[name] ||= PrometheusExporter::Metric::Gauge.new("sidekiq_stats_#{name}", help) - gauge.observe(value) + gauge.observe(value, labels) end end end diff --git a/test/server/collector_test.rb b/test/server/collector_test.rb index 1f8a6ad..29d3b0b 100644 --- a/test/server/collector_test.rb +++ b/test/server/collector_test.rb @@ -751,13 +751,13 @@ def test_it_can_collect_sidekiq_process_metrics result = collector.prometheus_metrics_text assert( result.include?( - %Q[sidekiq_process_busy{labels="lab_1,lab_2",queues="queue_1,queue_2",quiet="false",tag="default",hostname="#{PrometheusExporter.hostname}",identity="hostname:0"} 1], + %Q[sidekiq_process_busy{service="service1",labels="lab_1,lab_2",queues="queue_1,queue_2",quiet="false",tag="default",hostname="#{PrometheusExporter.hostname}",identity="hostname:0"} 1], ), "has number of busy", ) assert( result.include?( - %Q[sidekiq_process_concurrency{labels="lab_1,lab_2",queues="queue_1,queue_2",quiet="false",tag="default",hostname="#{PrometheusExporter.hostname}",identity="hostname:0"} 2], + %Q[sidekiq_process_concurrency{service="service1",labels="lab_1,lab_2",queues="queue_1,queue_2",quiet="false",tag="default",hostname="#{PrometheusExporter.hostname}",identity="hostname:0"} 2], ), "has number of concurrency", ) @@ -790,14 +790,14 @@ def test_it_can_collect_sidekiq_stats_metrics end result = collector.prometheus_metrics_text - assert_includes(result, "sidekiq_stats_dead_size 1") - assert_includes(result, "sidekiq_stats_enqueued 2") - assert_includes(result, "sidekiq_stats_failed 3") - assert_includes(result, "sidekiq_stats_processed 4") - assert_includes(result, "sidekiq_stats_processes_size 5") - assert_includes(result, "sidekiq_stats_retry_size 6") - assert_includes(result, "sidekiq_stats_scheduled_size 7") - assert_includes(result, "sidekiq_stats_workers_size 8") + assert_includes(result, "sidekiq_stats_dead_size{service=\"service1\"} 1") + assert_includes(result, "sidekiq_stats_enqueued{service=\"service1\"} 2") + assert_includes(result, "sidekiq_stats_failed{service=\"service1\"} 3") + assert_includes(result, "sidekiq_stats_processed{service=\"service1\"} 4") + assert_includes(result, "sidekiq_stats_processes_size{service=\"service1\"} 5") + assert_includes(result, "sidekiq_stats_retry_size{service=\"service1\"} 6") + assert_includes(result, "sidekiq_stats_scheduled_size{service=\"service1\"} 7") + assert_includes(result, "sidekiq_stats_workers_size{service=\"service1\"} 8") mock_sidekiq_stats.verify mock_sidekiq_stats_new.verify end diff --git a/test/server/sidekiq_process_collector_test.rb b/test/server/sidekiq_process_collector_test.rb index c3a1d8b..205e2ea 100644 --- a/test/server/sidekiq_process_collector_test.rb +++ b/test/server/sidekiq_process_collector_test.rb @@ -77,4 +77,55 @@ def test_only_fresh_metrics_are_collected assert_equal expected, metrics.map(&:metric_text) end end + + def test_collecting_metrics_with_custom_labels + collector.collect( + "custom_labels" => { "service" => "payments", "env" => "prod" }, + "process" => { + "busy" => 3, + "concurrency" => 10, + "labels" => { + "labels" => "lab_a", + "queues" => "critical,default", + "quiet" => "false", + "tag" => "main", + "hostname" => "sidekiq-host", + "identity" => "sidekiq-host:1", + }, + }, + ) + + metrics = collector.metrics + expected = [ + 'sidekiq_process_busy{service="payments",env="prod",labels="lab_a",queues="critical,default",quiet="false",tag="main",hostname="sidekiq-host",identity="sidekiq-host:1"} 3', + 'sidekiq_process_concurrency{service="payments",env="prod",labels="lab_a",queues="critical,default",quiet="false",tag="main",hostname="sidekiq-host",identity="sidekiq-host:1"} 10', + ] + assert_equal expected, metrics.map(&:metric_text) + end + + def test_custom_labels_overridden_by_process_labels + collector.collect( + "custom_labels" => { "service" => "billing", "tag" => "override" }, + "process" => { + "busy" => 4, + "concurrency" => 8, + "labels" => { + "labels" => "lab_x", + "queues" => "default", + "quiet" => "true", + "tag" => "real_tag", + "hostname" => "host-1", + "identity" => "host-1:2", + }, + }, + ) + + # tag should be from process labels (real_tag) not custom_labels (override) + metrics = collector.metrics + expected = [ + 'sidekiq_process_busy{service="billing",tag="real_tag",labels="lab_x",queues="default",quiet="true",hostname="host-1",identity="host-1:2"} 4', + 'sidekiq_process_concurrency{service="billing",tag="real_tag",labels="lab_x",queues="default",quiet="true",hostname="host-1",identity="host-1:2"} 8', + ] + assert_equal expected, metrics.map(&:metric_text) + end end diff --git a/test/server/sidekiq_stats_collector_test.rb b/test/server/sidekiq_stats_collector_test.rb index 060af83..f6d4c8a 100644 --- a/test/server/sidekiq_stats_collector_test.rb +++ b/test/server/sidekiq_stats_collector_test.rb @@ -39,6 +39,38 @@ def test_collecting_metrics assert_equal expected, metrics.map(&:metric_text) end + def test_collecting_metrics_with_custom_labels + collector.collect( + "stats" => { + "dead_size" => 1, + "enqueued" => 2, + "failed" => 3, + "processed" => 4, + "processes_size" => 5, + "retry_size" => 6, + "scheduled_size" => 7, + "workers_size" => 8, + }, + "custom_labels" => { + "service" => "test", + "foo" => "bar", + }, + ) + + metrics = collector.metrics + expected = [ + "sidekiq_stats_dead_size{service=\"test\",foo=\"bar\"} 1", + "sidekiq_stats_enqueued{service=\"test\",foo=\"bar\"} 2", + "sidekiq_stats_failed{service=\"test\",foo=\"bar\"} 3", + "sidekiq_stats_processed{service=\"test\",foo=\"bar\"} 4", + "sidekiq_stats_processes_size{service=\"test\",foo=\"bar\"} 5", + "sidekiq_stats_retry_size{service=\"test\",foo=\"bar\"} 6", + "sidekiq_stats_scheduled_size{service=\"test\",foo=\"bar\"} 7", + "sidekiq_stats_workers_size{service=\"test\",foo=\"bar\"} 8", + ] + assert_equal expected, metrics.map(&:metric_text) + end + def test_only_fresh_metrics_are_collected stub_monotonic_clock(1.0) do collector.collect(