sidekiq_prometheus 1.8.2 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cfef2dcf926147bf8113fc2ef76ebc53e194b742bff8024e52915829ed315403
4
- data.tar.gz: d312f2be0b37be88b32e4031560c03ad1386283c935e911435ba8929c108dc2b
3
+ metadata.gz: 654002b3b3138eef5307c4e4c3cab5a6d8ca45cc283c49341d3c1760f4d3ef67
4
+ data.tar.gz: 5abf477f0a4a8baa64e82d22527477614d57f48c8bf26c4d637a7c24bbb5cc70
5
5
  SHA512:
6
- metadata.gz: edc39e79efebc8d713ab0b4c60913b860c115fd99e6b8d096e705e41c698accb8e1765316e98371f67bd13c53e612254f656cf49713580b50675b15f8c9664f3
7
- data.tar.gz: d03bdf927308ed353d34922c894c0363e68e1326792d95dd7052f87c2a38d2156a6cfd13954b3ee593adbc9a7e80407a84569387ead503ea5adcb1f2baccf955
6
+ metadata.gz: 0544dc888a169886f532b2aa08ef8ab3c8c34ec1dea5a72bb9a75618aecfaaf4d1de81f6ae44cd61cc2621189ad69489a082f4af877cf63e7139ca3eb124a8dc
7
+ data.tar.gz: 7eb8689d5514e3585a6ee722a5f21d6f964a56146750d922fa578164a72ffbb36415c47befb10f7f7c61cc82ada60c7a4200b55370cf74ceae72270f4b423d98
data/.travis.yml CHANGED
@@ -1,8 +1,7 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
+ - 3.1
4
5
  - 3.0
5
6
  - 2.7
6
- - 2.6
7
- - 2.5
8
7
  before_install: gem install bundler -v 2.2.15
data/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  CHANGELOG
2
2
 
3
+ <a name="v1.8.3"></a>
4
+ ## [v1.8.3](https://github.com/fastly/sidekiq-prometheus/compare/v1.8.2...v1.8.3) (2023-01-30)
5
+
6
+ ## What's Changed
7
+ * Track leader state so that can unregister when demoted by @leklund in https://github.com/fastly/sidekiq-prometheus/pull/36
8
+
9
+ **Full Changelog**: https://github.com/fastly/sidekiq-prometheus/compare/v1.8.2...v1.8.3
10
+
11
+ <a name="v1.8.2"></a>
12
+ ## [v1.8.2](https://github.com/fastly/sidekiq-prometheus/compare/v1.8.1...v1.8.2) (2022-11-29)
13
+
14
+ ## What's Changed
15
+ * Allow sidekiq-prometheus to work with prometheus-client version > 2 by @hieuk09 in https://github.com/fastly/sidekiq-prometheus/pull/29
16
+ * Fixes Newer Sidekiq-Enterprise versions that have a Senate.leader? issue with Sidekiq Prometheus 1.8.1 by @imightbeinatree in https://github.com/fastly/sidekiq-prometheus/pull/32
17
+
18
+ ## New Contributors
19
+ * @hieuk09 made their first contribution in https://github.com/fastly/sidekiq-prometheus/pull/29
20
+
21
+ **Full Changelog**: https://github.com/fastly/sidekiq-prometheus/compare/v1.8.1...v1.8.2
22
+
3
23
  <a name="v1.8.1"></a>
4
24
  ## [v1.8.1](https://github.com/fastly/sidekiq-prometheus/compare/v1.8.0...v1.8.1) (2022-10-18)
5
25
 
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- source 'https://rubygems.org'
3
+ source "https://rubygems.org"
4
4
 
5
5
  git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
6
 
data/README.md CHANGED
@@ -79,6 +79,7 @@ end
79
79
  * `custom_labels`: Hash of metrics and labels that can be applied to specific metrics. The metric name must be a registered metric. `Hash{Symbol (metric name) => Array<Symbol> (label names)}`
80
80
  * `gc_metrics_enabled`: Boolean that determines whether to record object allocation metrics per job. The default is `true`. Setting this to `false` if you don't need this metric.
81
81
  * `global_metrics_enabled`: Boolean that determines whether to report global metrics from the PeriodicMetrics reporter. When `true` this will report on a number of stats from the Sidekiq API for the cluster. This requires Sidekiq::Enterprise as the reporter uses the leader election functionality to ensure that only one worker per cluster is reporting metrics.
82
+ * `init_label_sets`: Hash of metrics and label sets that are initialized by calling `metric.init_label_set` after the metric is registered. See[ prometheus-client docs](https://github.com/prometheus/client_ruby/tree/e144d6225d3c346e9a4dd0a11f41f8acde386dd8#init_label_set) for details. `Hash{Symbol (metric name) => Array<Hash> (label sets)}`.
82
83
  * `periodic_metrics_enabled`: Boolean that determines whether to run the periodic metrics reporter. `PeriodicMetrics` runs a separate thread that reports on global metrics (if enabled) as well worker GC stats (if enabled). It reports metrics on the interval defined by `periodic_reporting_interval`. Defaults to `true`.
83
84
  * `periodic_reporting_interval`: interval in seconds for reporting periodic metrics. Default: `30`
84
85
  * `metrics_server_enabled`: Boolean that determines whether to run the rack server. Defaults to `true`
@@ -94,6 +95,7 @@ SidekiqPrometheus.configure do |config|
94
95
  config.custom_labels = { sidekiq_job_count: [:worker_class, :job_type, :any_other_label] }
95
96
  config.gc_metrics_enabled = false
96
97
  config.global_metrics_enabled = true
98
+ config.init_label_sets = { sidekiq_job_count: [{worker_class: "class", job_type: "single", any_other_label: "value"}, {worker_class: "class", job_type: "batch", any_other_label: "other-value"}] }
97
99
  config.periodic_metrics_enabled = true
98
100
  config.periodic_reporting_interval = 20
99
101
  config.metrics_server_enabled = true
@@ -101,7 +103,7 @@ SidekiqPrometheus.configure do |config|
101
103
  end
102
104
  ```
103
105
 
104
- Custom labels may be added by defining the `prometheus_labels` method in the worker class,
106
+ Custom labels may be added by defining the `prometheus_labels` method in the worker class,
105
107
  prior you need to register the custom labels as of the above example:
106
108
 
107
109
  ```ruby
@@ -130,10 +132,13 @@ All Sidekiq job metrics are reported with these labels:
130
132
  | sidekiq_job_success | counter | Count of successful Sidekiq jobs |
131
133
  | sidekiq_job_allocated_objects | histogram | Count of ruby objects allocated by a Sidekiq job |
132
134
  | sidekiq_job_failed | counter | Count of failed Sidekiq jobs |
135
+ | sidekiq_job_over_limit | counter | Count of over limit Sidekiq jobs |
136
+
133
137
 
134
138
  Notes:
135
139
 
136
140
  * when a job fails only `sidekiq_job_count` and `sidekiq_job_failed` will be reported.
141
+ * when a job fails due to Sidekiq::Limiter::OverLimit error, only `sidekiq_job_count` and `sidekiq_job_over_limit` will be reported.
137
142
  * `sidekiq_job_allocated_objects` will only be reported if `SidekiqPrometheus.gc_metrics_enabled? == true`
138
143
 
139
144
  ### Periodic GC Metrics
@@ -217,7 +222,7 @@ There is also a method to register more than one metric at a time:
217
222
  customer_worker_metrics = [
218
223
  {
219
224
  name: :file_count, type: :counter, docstring: 'Number of active files',
220
- name: :file_size, type: :gauge, docstring: 'Size of files in bytes',
225
+ name: :file_size, type: :gauge, docstring: 'Size of files in bytes',
221
226
  }
222
227
  ]
223
228
 
data/Rakefile CHANGED
@@ -1,19 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'bundler/gem_tasks'
4
- require 'rspec/core/rake_task'
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+ require "standard/rake"
5
6
 
6
7
  RSpec::Core::RakeTask.new(:spec)
7
8
 
8
- begin
9
- require 'rubocop/rake_task'
10
- RuboCop::RakeTask.new(:rubocop) do |task|
11
- task.options = ['-c.rubocop.yml']
12
- end
13
- rescue LoadError
14
- end
15
-
16
9
  task default: %w[
17
- rubocop
10
+ standard
18
11
  spec
19
12
  ]
@@ -7,8 +7,8 @@ class SidekiqPrometheus::JobMetrics
7
7
  # If we're using a wrapper class, like ActiveJob, use the "wrapped"
8
8
  # attribute to expose the underlying thing.
9
9
  labels = {
10
- class: job['wrapped'] || worker.class.to_s,
11
- queue: queue,
10
+ class: job["wrapped"] || worker.class.to_s,
11
+ queue: queue
12
12
  }
13
13
 
14
14
  begin
@@ -29,11 +29,11 @@ class SidekiqPrometheus::JobMetrics
29
29
  end
30
30
 
31
31
  result
32
- rescue StandardError => e
33
- if e.class.to_s == 'Sidekiq::Limiter::OverLimit'
32
+ rescue => e
33
+ if e.instance_of?(::Sidekiq::Limiter::OverLimit)
34
34
  registry[:sidekiq_job_over_limit].increment(labels: labels)
35
35
  else
36
- err_label = { :error_class => e.class.to_s }
36
+ err_label = {error_class: e.class.to_s}
37
37
  registry[:sidekiq_job_failed].increment(labels: err_label.merge(labels))
38
38
  end
39
39
 
@@ -3,106 +3,106 @@
3
3
  module SidekiqPrometheus::Metrics
4
4
  module_function
5
5
 
6
- UNKNOWN = 'unknown'
6
+ UNKNOWN = "unknown"
7
7
 
8
8
  VALID_TYPES = %i[counter gauge histogram summary].freeze
9
9
  JOB_LABELS = %i[class queue].freeze
10
10
  SIDEKIQ_GLOBAL_METRICS = [
11
- { name: :sidekiq_workers_size,
12
- type: :gauge,
13
- docstring: 'Total number of workers processing jobs', },
14
- { name: :sidekiq_processes_size,
15
- type: :gauge,
16
- docstring: 'Total number of running sidekiq processes', },
17
- { name: :sidekiq_dead_size,
18
- type: :gauge,
19
- docstring: 'Total Dead Size', },
20
- { name: :sidekiq_enqueued,
21
- type: :gauge,
22
- docstring: 'Total Size of all known queues',
23
- labels: %i[queue], },
24
- { name: :sidekiq_queue_latency,
25
- type: :summary,
26
- docstring: 'Latency (in seconds) of all queues',
27
- labels: %i[queue], },
28
- { name: :sidekiq_failed,
29
- type: :gauge,
30
- docstring: 'Number of job executions which raised an error', },
31
- { name: :sidekiq_processed,
32
- type: :gauge,
33
- docstring: 'Number of job executions completed (success or failure)', },
34
- { name: :sidekiq_retry_size,
35
- type: :gauge,
36
- docstring: 'Total Retries Size', },
37
- { name: :sidekiq_scheduled_size,
38
- type: :gauge,
39
- docstring: 'Total Scheduled Size', },
40
- { name: :sidekiq_redis_connected_clients,
41
- type: :gauge,
42
- docstring: 'Number of clients connected to Redis instance for Sidekiq', },
43
- { name: :sidekiq_redis_used_memory,
44
- type: :gauge,
45
- docstring: 'Used memory from Redis.info', },
46
- { name: :sidekiq_redis_used_memory_peak,
47
- type: :gauge,
48
- docstring: 'Used memory peak from Redis.info', },
49
- { name: :sidekiq_redis_keys,
50
- type: :gauge,
51
- docstring: 'Number of redis keys',
52
- labels: %i[database], },
53
- { name: :sidekiq_redis_expires,
54
- type: :gauge,
55
- docstring: 'Number of redis keys with expiry set',
56
- labels: %i[database], },
11
+ {name: :sidekiq_workers_size,
12
+ type: :gauge,
13
+ docstring: "Total number of workers processing jobs"},
14
+ {name: :sidekiq_processes_size,
15
+ type: :gauge,
16
+ docstring: "Total number of running sidekiq processes"},
17
+ {name: :sidekiq_dead_size,
18
+ type: :gauge,
19
+ docstring: "Total Dead Size"},
20
+ {name: :sidekiq_enqueued,
21
+ type: :gauge,
22
+ docstring: "Total Size of all known queues",
23
+ labels: %i[queue]},
24
+ {name: :sidekiq_queue_latency,
25
+ type: :summary,
26
+ docstring: "Latency (in seconds) of all queues",
27
+ labels: %i[queue]},
28
+ {name: :sidekiq_failed,
29
+ type: :gauge,
30
+ docstring: "Number of job executions which raised an error"},
31
+ {name: :sidekiq_processed,
32
+ type: :gauge,
33
+ docstring: "Number of job executions completed (success or failure)"},
34
+ {name: :sidekiq_retry_size,
35
+ type: :gauge,
36
+ docstring: "Total Retries Size"},
37
+ {name: :sidekiq_scheduled_size,
38
+ type: :gauge,
39
+ docstring: "Total Scheduled Size"},
40
+ {name: :sidekiq_redis_connected_clients,
41
+ type: :gauge,
42
+ docstring: "Number of clients connected to Redis instance for Sidekiq"},
43
+ {name: :sidekiq_redis_used_memory,
44
+ type: :gauge,
45
+ docstring: "Used memory from Redis.info"},
46
+ {name: :sidekiq_redis_used_memory_peak,
47
+ type: :gauge,
48
+ docstring: "Used memory peak from Redis.info"},
49
+ {name: :sidekiq_redis_keys,
50
+ type: :gauge,
51
+ docstring: "Number of redis keys",
52
+ labels: %i[database]},
53
+ {name: :sidekiq_redis_expires,
54
+ type: :gauge,
55
+ docstring: "Number of redis keys with expiry set",
56
+ labels: %i[database]}
57
57
  ].freeze
58
58
  SIDEKIQ_JOB_METRICS = [
59
- { name: :sidekiq_job_count,
60
- type: :counter,
61
- docstring: 'Count of Sidekiq jobs',
62
- labels: JOB_LABELS, },
63
- { name: :sidekiq_job_duration,
64
- type: :histogram,
65
- docstring: 'Sidekiq job processing duration',
66
- labels: JOB_LABELS, },
67
- { name: :sidekiq_job_failed,
68
- type: :counter,
69
- docstring: 'Count of failed Sidekiq jobs',
70
- labels: JOB_LABELS + [:error_class], },
71
- { name: :sidekiq_job_success,
72
- type: :counter,
73
- docstring: 'Count of successful Sidekiq jobs',
74
- labels: JOB_LABELS, },
75
- { name: :sidekiq_job_over_limit,
76
- type: :counter,
77
- docstring: 'Count of over limit Sidekiq jobs',
78
- labels: JOB_LABELS, },
59
+ {name: :sidekiq_job_count,
60
+ type: :counter,
61
+ docstring: "Count of Sidekiq jobs",
62
+ labels: JOB_LABELS},
63
+ {name: :sidekiq_job_duration,
64
+ type: :histogram,
65
+ docstring: "Sidekiq job processing duration",
66
+ labels: JOB_LABELS},
67
+ {name: :sidekiq_job_failed,
68
+ type: :counter,
69
+ docstring: "Count of failed Sidekiq jobs",
70
+ labels: JOB_LABELS + [:error_class]},
71
+ {name: :sidekiq_job_success,
72
+ type: :counter,
73
+ docstring: "Count of successful Sidekiq jobs",
74
+ labels: JOB_LABELS},
75
+ {name: :sidekiq_job_over_limit,
76
+ type: :counter,
77
+ docstring: "Count of over limit Sidekiq jobs",
78
+ labels: JOB_LABELS}
79
79
  ].freeze
80
80
  SIDEKIQ_GC_METRIC = {
81
- name: :sidekiq_job_allocated_objects,
82
- type: :histogram,
83
- docstring: 'Count of ruby objects allocated by a Sidekiq job',
84
- buckets: [10, 50, 100, 500, 1_000, 2_500, 5_000, 10_000, 50_000, 100_000, 500_000, 1_000_000, 5_000_000, 10_000_000, 25_000_000],
85
- labels: JOB_LABELS,
81
+ name: :sidekiq_job_allocated_objects,
82
+ type: :histogram,
83
+ docstring: "Count of ruby objects allocated by a Sidekiq job",
84
+ buckets: [10, 50, 100, 500, 1_000, 2_500, 5_000, 10_000, 50_000, 100_000, 500_000, 1_000_000, 5_000_000, 10_000_000, 25_000_000],
85
+ labels: JOB_LABELS
86
86
  }.freeze
87
87
  SIDEKIQ_WORKER_GC_METRICS = [
88
- { name: :sidekiq_allocated_objects,
89
- type: :counter,
90
- docstring: 'Count of ruby objects allocated by a Sidekiq worker', },
91
- { name: :sidekiq_heap_free_slots,
92
- type: :gauge,
93
- docstring: 'Sidekiq worker GC.stat[:heap_free_slots]', },
94
- { name: :sidekiq_heap_live_slots,
95
- type: :gauge,
96
- docstring: 'Sidekiq worker GC.stat[:heap_live_slots]', },
97
- { name: :sidekiq_major_gc_count,
98
- type: :counter,
99
- docstring: 'Sidekiq worker GC.stat[:major_gc_count]', },
100
- { name: :sidekiq_minor_gc_count,
101
- type: :counter,
102
- docstring: 'Sidekiq worker GC.stat[:minor_gc_count]', },
103
- { name: :sidekiq_rss,
104
- type: :gauge,
105
- docstring: 'Sidekiq process RSS', },
88
+ {name: :sidekiq_allocated_objects,
89
+ type: :counter,
90
+ docstring: "Count of ruby objects allocated by a Sidekiq worker"},
91
+ {name: :sidekiq_heap_free_slots,
92
+ type: :gauge,
93
+ docstring: "Sidekiq worker GC.stat[:heap_free_slots]"},
94
+ {name: :sidekiq_heap_live_slots,
95
+ type: :gauge,
96
+ docstring: "Sidekiq worker GC.stat[:heap_live_slots]"},
97
+ {name: :sidekiq_major_gc_count,
98
+ type: :counter,
99
+ docstring: "Sidekiq worker GC.stat[:major_gc_count]"},
100
+ {name: :sidekiq_minor_gc_count,
101
+ type: :counter,
102
+ docstring: "Sidekiq worker GC.stat[:minor_gc_count]"},
103
+ {name: :sidekiq_rss,
104
+ type: :gauge,
105
+ docstring: "Sidekiq process RSS"}
106
106
  ].freeze
107
107
 
108
108
  def registry
@@ -131,6 +131,16 @@ module SidekiqPrometheus::Metrics
131
131
  end
132
132
  end
133
133
 
134
+ def unregister_sidekiq_global_metrics
135
+ unregister_metrics SIDEKIQ_GLOBAL_METRICS
136
+ end
137
+
138
+ def unregister_metrics(metrics)
139
+ metrics.each do |metric|
140
+ unregister(name: metric[:name])
141
+ end
142
+ end
143
+
134
144
  ##
135
145
  # Fetch a metric from the registry
136
146
  # @param name [Symbol] name of metric to fetch
@@ -139,7 +149,7 @@ module SidekiqPrometheus::Metrics
139
149
  end
140
150
 
141
151
  class << self
142
- alias get []
152
+ alias_method :get, :[]
143
153
  end
144
154
 
145
155
  ##
@@ -160,13 +170,18 @@ module SidekiqPrometheus::Metrics
160
170
  # Aggregate all labels
161
171
  all_labels = labels | SidekiqPrometheus.custom_labels.fetch(name, []) | all_preset_labels.keys
162
172
 
163
- options = { docstring: docstring,
164
- labels: all_labels,
165
- preset_labels: all_preset_labels, }
173
+ options = {docstring: docstring,
174
+ labels: all_labels,
175
+ preset_labels: all_preset_labels}
166
176
 
167
177
  options[:buckets] = buckets if buckets
168
178
 
169
- registry.send(type, name.to_sym, **options)
179
+ metric = registry.send(type, name.to_sym, **options)
180
+
181
+ init_label_sets = SidekiqPrometheus.init_label_sets.fetch(name, [])
182
+ init_label_sets.each { |label_set| metric.init_label_set(label_set) }
183
+
184
+ metric
170
185
  end
171
186
 
172
187
  def unregister(name:)
@@ -11,7 +11,7 @@
11
11
  # @see https://github.com/mperham/sidekiq/blob/main/lib/sidekiq/api.rb
12
12
 
13
13
  begin
14
- require 'sidekiq/component'
14
+ require "sidekiq/component"
15
15
  rescue LoadError
16
16
  end
17
17
 
@@ -21,6 +21,9 @@ class SidekiqPrometheus::PeriodicMetrics
21
21
  # @return [Boolean] When +true+ will stop the reporting loop.
22
22
  attr_accessor :done
23
23
 
24
+ # @return [Boolean] Indicates if this instance is currently the leader.
25
+ attr_accessor :leader
26
+
24
27
  # @return [Integer] Interval in seconds to record metrics. Default: [SidekiqPrometheus.periodic_reporting_interval]
25
28
  attr_reader :interval
26
29
  attr_reader :senate, :sidekiq_stats, :sidekiq_queue
@@ -28,7 +31,7 @@ class SidekiqPrometheus::PeriodicMetrics
28
31
  GLOBAL_STATS = %i[failed processed retry_size dead_size scheduled_size workers_size processes_size].freeze
29
32
  GC_STATS = {
30
33
  counters: %i[major_gc_count minor_gc_count total_allocated_objects],
31
- gauges: %i[heap_live_slots heap_free_slots],
34
+ gauges: %i[heap_live_slots heap_free_slots]
32
35
  }.freeze
33
36
  REDIS_STATS = %w[connected_clients used_memory used_memory_peak].freeze
34
37
 
@@ -50,24 +53,25 @@ class SidekiqPrometheus::PeriodicMetrics
50
53
  @sidekiq_stats = sidekiq_stats
51
54
  @sidekiq_queue = sidekiq_queue
52
55
  @senate = if senate.nil?
53
- if Object.const_defined?('Sidekiq::Senate')
54
- if respond_to?(:leader?)
55
- self
56
- else
57
- Sidekiq::Senate
58
- end
59
- else
60
- Senate
61
- end
62
- else
63
- senate
64
- end
56
+ if Object.const_defined?("Sidekiq::Senate")
57
+ if respond_to?(:leader?)
58
+ self
59
+ else
60
+ Sidekiq::Senate
61
+ end
62
+ else
63
+ Senate
64
+ end
65
+ else
66
+ senate
67
+ end
68
+ @leader = false
65
69
  end
66
70
 
67
71
  ##
68
72
  # Start the period mettric reporter
69
73
  def start
70
- Sidekiq.logger.info('SidekiqPrometheus: Starting periodic metrics reporting')
74
+ Sidekiq.logger.info("SidekiqPrometheus: Starting periodic metrics reporting")
71
75
  @thread = Thread.new(&method(:run))
72
76
  end
73
77
 
@@ -100,8 +104,8 @@ class SidekiqPrometheus::PeriodicMetrics
100
104
  end
101
105
 
102
106
  sidekiq_queue.all.each do |queue|
103
- SidekiqPrometheus[:sidekiq_enqueued]&.set(queue.size, labels: { queue: queue.name })
104
- SidekiqPrometheus[:sidekiq_queue_latency]&.observe(queue.latency, labels: { queue: queue.name })
107
+ SidekiqPrometheus[:sidekiq_enqueued]&.set(queue.size, labels: {queue: queue.name})
108
+ SidekiqPrometheus[:sidekiq_queue_latency]&.observe(queue.latency, labels: {queue: queue.name})
105
109
  end
106
110
  end
107
111
 
@@ -122,7 +126,7 @@ class SidekiqPrometheus::PeriodicMetrics
122
126
 
123
127
  db_stats = redis_info.select { |k, _v| k.match(/^db/) }
124
128
  db_stats.each do |db, stat|
125
- label = { database: db }
129
+ label = {database: db}
126
130
  values = stat.scan(/\d+/)
127
131
  SidekiqPrometheus[:sidekiq_redis_keys]&.set(values[0].to_i, labels: label)
128
132
  SidekiqPrometheus[:sidekiq_redis_expires]&.set(values[1].to_i, labels: label)
@@ -134,8 +138,16 @@ class SidekiqPrometheus::PeriodicMetrics
134
138
  # @see https://github.com/discourse/prometheus_exporter/blob/v0.3.3/lib/prometheus_exporter/instrumentation/process.rb#L39-L42
135
139
  def rss
136
140
  pid = Process.pid
137
- @pagesize ||= `getconf PAGESIZE`.to_i rescue 4096
138
- File.read("/proc/#{pid}/statm").split(' ')[1].to_i * @pagesize rescue 0
141
+ @pagesize ||= begin
142
+ `getconf PAGESIZE`.to_i
143
+ rescue
144
+ 4096
145
+ end
146
+ begin
147
+ File.read("/proc/#{pid}/statm").split(" ")[1].to_i * @pagesize
148
+ rescue
149
+ 0
150
+ end
139
151
  end
140
152
 
141
153
  ##
@@ -144,10 +156,14 @@ class SidekiqPrometheus::PeriodicMetrics
144
156
  def run
145
157
  until done
146
158
  begin
147
- report_global_metrics if SidekiqPrometheus.global_metrics_enabled? && senate.leader?
148
- report_redis_metrics if SidekiqPrometheus.global_metrics_enabled? && senate.leader?
159
+ if SidekiqPrometheus.global_metrics_enabled?
160
+ handle_leader_state(senate.leader?)
161
+ report_global_metrics if leader
162
+ report_redis_metrics if leader
163
+ end
164
+
149
165
  report_gc_metrics if SidekiqPrometheus.gc_metrics_enabled?
150
- rescue StandardError => e
166
+ rescue => e
151
167
  Sidekiq.logger.error e
152
168
  ensure
153
169
  sleep interval
@@ -155,6 +171,22 @@ class SidekiqPrometheus::PeriodicMetrics
155
171
  end
156
172
  end
157
173
 
174
+ ##
175
+ # If this instance was promoted to the leader set the local state and register the metrics.
176
+ def handle_leader_state(senate_leader)
177
+ return if senate_leader == leader
178
+
179
+ if senate_leader && !leader
180
+ # This instance is now the leader
181
+ self.leader = true
182
+ SidekiqPrometheus::Metrics.register_sidekiq_global_metrics
183
+ else
184
+ # we've been demoted!
185
+ SidekiqPrometheus::Metrics.unregister_sidekiq_global_metrics
186
+ self.leader = false
187
+ end
188
+ end
189
+
158
190
  ##
159
191
  # Fake Senate class to guard against undefined constant errors.
160
192
  # @private
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SidekiqPrometheus
4
- VERSION = '1.8.2'
4
+ VERSION = "1.9.0"
5
5
  end
@@ -1,15 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'benchmark'
4
- require 'rack'
5
- require 'prometheus/client'
6
- require 'prometheus/middleware/exporter'
7
- require 'sidekiq'
8
- require 'sidekiq/api'
9
- require 'webrick'
3
+ require "benchmark"
4
+ require "rack"
5
+ require "prometheus/client"
6
+ require "prometheus/middleware/exporter"
7
+ require "sidekiq"
8
+ require "sidekiq/api"
9
+ require "webrick"
10
10
 
11
11
  begin
12
- require 'sidekiq/ent'
12
+ require "sidekiq/ent"
13
13
  rescue LoadError
14
14
  end
15
15
 
@@ -42,6 +42,14 @@ module SidekiqPrometheus
42
42
  # @return [Boolean] Setting to control enabling/disabling global metrics. Default: true
43
43
  attr_accessor :global_metrics_enabled
44
44
 
45
+ # @return [Hash{Symbol => Array(Hash)}] Label sets that will be initiliazed when a metric is registered.
46
+ # @example
47
+ # {
48
+ # metric_name: [{label: 'value1', other_label: 'value1'}, {label: 'value1', other_label: 'value2'}],
49
+ # another_metric_name: [{label: 'value1', other_label: 'value1'}]
50
+ # }
51
+ attr_accessor :init_label_sets
52
+
45
53
  # @return [Boolean] Setting to control enabling/disabling periodic metrics. Default: true
46
54
  attr_accessor :periodic_metrics_enabled
47
55
 
@@ -77,11 +85,12 @@ module SidekiqPrometheus
77
85
  self.global_metrics_enabled = true
78
86
  self.periodic_reporting_interval = 30
79
87
  self.metrics_server_enabled = true
80
- self.metrics_host = 'localhost'
88
+ self.metrics_host = "localhost"
81
89
  self.metrics_port = 9359
82
90
  self.metrics_server_logger_enabled = true
83
91
  self.custom_labels = {}
84
92
  self.custom_metrics = []
93
+ self.init_label_sets = {}
85
94
 
86
95
  module_function
87
96
 
@@ -115,7 +124,7 @@ module SidekiqPrometheus
115
124
  # Requires +Sidekiq::Enterprise+ as it uses the leader election functionality
116
125
  # @return [Boolean] defaults to true if +Sidekiq::Enterprise+ is available
117
126
  def global_metrics_enabled?
118
- Object.const_defined?('Sidekiq::Enterprise') && global_metrics_enabled
127
+ Object.const_defined?("Sidekiq::Enterprise") && global_metrics_enabled
119
128
  end
120
129
 
121
130
  ##
@@ -149,8 +158,8 @@ module SidekiqPrometheus
149
158
  end
150
159
 
151
160
  class << self
152
- alias configure! configure
153
- alias get []
161
+ alias_method :configure!, :configure
162
+ alias_method :get, :[]
154
163
  end
155
164
 
156
165
  ##
@@ -166,7 +175,7 @@ module SidekiqPrometheus
166
175
  def register_custom_metrics
167
176
  return if custom_metrics.empty?
168
177
 
169
- raise SidekiqPrometheus::Error, 'custom_metrics is not an array.' unless custom_metrics.is_a?(Array)
178
+ raise SidekiqPrometheus::Error, "custom_metrics is not an array." unless custom_metrics.is_a?(Array)
170
179
 
171
180
  SidekiqPrometheus::Metrics.register_metrics(custom_metrics)
172
181
  end
@@ -178,7 +187,6 @@ module SidekiqPrometheus
178
187
  SidekiqPrometheus::Metrics.register_sidekiq_job_metrics
179
188
  SidekiqPrometheus::Metrics.register_sidekiq_gc_metric if gc_metrics_enabled?
180
189
  SidekiqPrometheus::Metrics.register_sidekiq_worker_gc_metrics if gc_metrics_enabled? && periodic_metrics_enabled?
181
- SidekiqPrometheus::Metrics.register_sidekiq_global_metrics if global_metrics_enabled? && periodic_metrics_enabled?
182
190
  register_custom_metrics
183
191
 
184
192
  sidekiq_setup
@@ -195,12 +203,12 @@ module SidekiqPrometheus
195
203
  end
196
204
 
197
205
  if periodic_metrics_enabled?
198
- config.on(:startup) { SidekiqPrometheus::PeriodicMetrics.reporter(config).start }
206
+ config.on(:startup) { SidekiqPrometheus::PeriodicMetrics.reporter(config).start }
199
207
  config.on(:shutdown) { SidekiqPrometheus::PeriodicMetrics.reporter(config).stop }
200
208
  end
201
209
 
202
210
  if metrics_server_enabled?
203
- config.on(:startup) { SidekiqPrometheus.metrics_server }
211
+ config.on(:startup) { SidekiqPrometheus.metrics_server }
204
212
  config.on(:shutdown) { SidekiqPrometheus.metrics_server.kill }
205
213
  end
206
214
  end
@@ -213,11 +221,11 @@ module SidekiqPrometheus
213
221
  def metrics_server
214
222
  opts = {
215
223
  Port: SidekiqPrometheus.metrics_port,
216
- Host: SidekiqPrometheus.metrics_host,
224
+ Host: SidekiqPrometheus.metrics_host
217
225
  }
218
226
 
219
227
  unless metrics_server_logger_enabled?
220
- opts[:Logger] = WEBrick::Log.new('/dev/null')
228
+ opts[:Logger] = WEBrick::Log.new("/dev/null")
221
229
  opts[:AccessLog] = []
222
230
  end
223
231
 
@@ -225,7 +233,7 @@ module SidekiqPrometheus
225
233
  Rack::Handler::WEBrick.run(
226
234
  Rack::Builder.new {
227
235
  use Prometheus::Middleware::Exporter, registry: SidekiqPrometheus.registry
228
- run ->(_) { [301, { 'Location' => '/metrics' }, []] }
236
+ run ->(_) { [301, {"Location" => "/metrics"}, []] }
229
237
  },
230
238
  **opts
231
239
  )
@@ -235,7 +243,7 @@ end
235
243
 
236
244
  class SidekiqPrometheus::Error < StandardError; end
237
245
 
238
- require 'sidekiq_prometheus/job_metrics'
239
- require 'sidekiq_prometheus/metrics'
240
- require 'sidekiq_prometheus/periodic_metrics'
241
- require 'sidekiq_prometheus/version'
246
+ require "sidekiq_prometheus/job_metrics"
247
+ require "sidekiq_prometheus/metrics"
248
+ require "sidekiq_prometheus/periodic_metrics"
249
+ require "sidekiq_prometheus/version"
@@ -1,34 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- lib = File.expand_path('lib', __dir__)
3
+ lib = File.expand_path("lib", __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
- require 'sidekiq_prometheus/version'
5
+ require "sidekiq_prometheus/version"
6
6
 
7
7
  Gem::Specification.new do |spec|
8
- spec.name = 'sidekiq_prometheus'
9
- spec.version = SidekiqPrometheus::VERSION
10
- spec.authors = ['Lukas Eklund', 'NHM Tanveer Hossain Khan']
11
- spec.email = ['leklund@fastly.com']
8
+ spec.name = "sidekiq_prometheus"
9
+ spec.version = SidekiqPrometheus::VERSION
10
+ spec.authors = ["Lukas Eklund", "NHM Tanveer Hossain Khan"]
11
+ spec.email = ["leklund@fastly.com"]
12
12
 
13
- spec.summary = 'Prometheus Instrumentation for Sidekiq'
14
- spec.homepage = 'https://github.com/fastly/sidekiq-prometheus'
15
- spec.license = 'MIT'
13
+ spec.summary = "Prometheus Instrumentation for Sidekiq"
14
+ spec.homepage = "https://github.com/fastly/sidekiq-prometheus"
15
+ spec.license = "MIT"
16
16
 
17
17
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
18
  f.match(%r{^(test|spec|features)/})
19
19
  end
20
- spec.bindir = 'exe'
21
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
- spec.require_paths = ['lib']
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
23
 
24
- spec.add_development_dependency 'bundler'
25
- spec.add_development_dependency 'pry'
26
- spec.add_development_dependency 'rake', '~> 12.3.3'
27
- spec.add_development_dependency 'rspec', '~> 3.0'
28
- spec.add_development_dependency 'rubocop', '~> 0.58.0'
24
+ spec.add_development_dependency "bundler"
25
+ spec.add_development_dependency "pry"
26
+ spec.add_development_dependency "rake", "~> 12.3.3"
27
+ spec.add_development_dependency "rspec", "~> 3.0"
28
+ spec.add_development_dependency "standard"
29
29
 
30
- spec.add_runtime_dependency 'prometheus-client', '>= 2.0'
31
- spec.add_runtime_dependency 'rack'
32
- spec.add_runtime_dependency 'sidekiq', '> 5.1', '< 7.0'
33
- spec.add_runtime_dependency 'webrick'
30
+ spec.add_runtime_dependency "prometheus-client", ">= 2.0"
31
+ spec.add_runtime_dependency "rack"
32
+ spec.add_runtime_dependency "sidekiq", "> 5.1", "< 7.0"
33
+ spec.add_runtime_dependency "webrick"
34
34
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq_prometheus
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.2
4
+ version: 1.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lukas Eklund
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2022-11-29 00:00:00.000000000 Z
12
+ date: 2023-08-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -68,19 +68,19 @@ dependencies:
68
68
  - !ruby/object:Gem::Version
69
69
  version: '3.0'
70
70
  - !ruby/object:Gem::Dependency
71
- name: rubocop
71
+ name: standard
72
72
  requirement: !ruby/object:Gem::Requirement
73
73
  requirements:
74
- - - "~>"
74
+ - - ">="
75
75
  - !ruby/object:Gem::Version
76
- version: 0.58.0
76
+ version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
- - - "~>"
81
+ - - ">="
82
82
  - !ruby/object:Gem::Version
83
- version: 0.58.0
83
+ version: '0'
84
84
  - !ruby/object:Gem::Dependency
85
85
  name: prometheus-client
86
86
  requirement: !ruby/object:Gem::Requirement
@@ -188,7 +188,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
188
188
  - !ruby/object:Gem::Version
189
189
  version: '0'
190
190
  requirements: []
191
- rubygems_version: 3.1.6
191
+ rubygems_version: 3.3.7
192
192
  signing_key:
193
193
  specification_version: 4
194
194
  summary: Prometheus Instrumentation for Sidekiq