sidekiq_prometheus 1.8.2 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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