prometheus_exporter 0.4.14 → 0.4.15
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 +4 -4
- data/CHANGELOG +7 -0
- data/README.md +66 -0
- data/lib/prometheus_exporter/client.rb +5 -5
- data/lib/prometheus_exporter/instrumentation.rb +1 -0
- data/lib/prometheus_exporter/instrumentation/active_record.rb +98 -0
- data/lib/prometheus_exporter/instrumentation/delayed_job.rb +7 -3
- data/lib/prometheus_exporter/instrumentation/unicorn.rb +1 -1
- data/lib/prometheus_exporter/server.rb +1 -0
- data/lib/prometheus_exporter/server/active_record_collector.rb +56 -0
- data/lib/prometheus_exporter/server/collector.rb +8 -2
- data/lib/prometheus_exporter/server/delayed_job_collector.rb +12 -1
- data/lib/prometheus_exporter/server/process_collector.rb +1 -0
- data/lib/prometheus_exporter/server/unicorn_collector.rb +3 -1
- data/lib/prometheus_exporter/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 86155ae93296d42918b6419efbdae95665e5149a89083894dd9ba5daaf9f84bf
|
4
|
+
data.tar.gz: 49bee52b66976743b17794f7515cc57c7c6979338d479a66ec49ae0ff30d9f7f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c2ebf589c432b5c64339d15c4c25b99d4cca49228c466ba9a334c4af12b2ac7c7922a8607c9c90ea38cf1afd9a2f2efa5dde087ab4aed8f124e4f2577510ee11
|
7
|
+
data.tar.gz: e1a2f8f93f59b62296ce1a2448f70c3decd8f970787ee5619593080da6e181c02c432e82e52ac9de11f626309eb9aa513e6070c56349ef84fcf3a84d4b44ea45
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
0.4.15 - 04-11-2019
|
2
|
+
|
3
|
+
- FEATURE: Improve delayed job collector, add pending counts
|
4
|
+
- FEATURE: New ActiveRecord collector (documented in readme)
|
5
|
+
- FEATURE: Allow passing in histogram and summary options
|
6
|
+
- FEATURE: Allow custom labels for unicorn collector
|
7
|
+
|
1
8
|
0.4.14 - 10-09-2019
|
2
9
|
|
3
10
|
- FEATURE: allow finding metrics by name RemoteMetric #find_registered_metric
|
data/README.md
CHANGED
@@ -13,6 +13,7 @@ To learn more see [Instrumenting Rails with Prometheus](https://samsaffron.com/a
|
|
13
13
|
* [Rails integration](#rails-integration)
|
14
14
|
* [Per-process stats](#per-process-stats)
|
15
15
|
* [Sidekiq metrics](#sidekiq-metrics)
|
16
|
+
* [ActiveRecord Connection Pool Metrics](#activerecord-connection-pool-metrics)
|
16
17
|
* [Delayed Job plugin](#delayed-job-plugin)
|
17
18
|
* [Hutch metrics](#hutch-message-processing-tracer)
|
18
19
|
* [Puma metrics](#puma-metrics)
|
@@ -148,6 +149,17 @@ awesome 10
|
|
148
149
|
|
149
150
|
```
|
150
151
|
|
152
|
+
Custom quantiles for summaries and buckets for histograms can also be passed in.
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
require 'prometheus_exporter/client'
|
156
|
+
|
157
|
+
client = PrometheusExporter::Client.default
|
158
|
+
histogram = client.register(:histogram, "api_time", "time to call api", buckets: [0.1, 0.5, 1])
|
159
|
+
|
160
|
+
histogram.observe(0.2, api: 'twitter')
|
161
|
+
```
|
162
|
+
|
151
163
|
### Rails integration
|
152
164
|
|
153
165
|
You can easily integrate into any Rack application.
|
@@ -175,6 +187,60 @@ Ensure you run the exporter in a monitored background process:
|
|
175
187
|
$ bundle exec prometheus_exporter
|
176
188
|
```
|
177
189
|
|
190
|
+
#### Activerecord Connection Pool Metrics
|
191
|
+
|
192
|
+
This collects activerecord connection pool metrics.
|
193
|
+
|
194
|
+
It supports injection of custom labels and the connection config options (`username`, `database`, `host`, `port`) as labels.
|
195
|
+
|
196
|
+
For Puma single mode
|
197
|
+
```ruby
|
198
|
+
#in puma.rb
|
199
|
+
require 'prometheus_exporter/instrumentation'
|
200
|
+
PrometheusExporter::Instrumentation::ActiveRecord.start(
|
201
|
+
custom_labels: { type: "puma_single_mode" }, #optional params
|
202
|
+
config_labels: [:database, :host] #optional params
|
203
|
+
)
|
204
|
+
```
|
205
|
+
|
206
|
+
For Puma cluster mode
|
207
|
+
|
208
|
+
```ruby
|
209
|
+
# in puma.rb
|
210
|
+
on_worker_boot do
|
211
|
+
require 'prometheus_exporter/instrumentation'
|
212
|
+
PrometheusExporter::Instrumentation::ActiveRecord.start(
|
213
|
+
custom_labels: { type: "puma_worker" }, #optional params
|
214
|
+
config_labels: [:database, :host] #optional params
|
215
|
+
)
|
216
|
+
end
|
217
|
+
```
|
218
|
+
|
219
|
+
For Unicorn / Passenger
|
220
|
+
|
221
|
+
```ruby
|
222
|
+
after_fork do
|
223
|
+
require 'prometheus_exporter/instrumentation'
|
224
|
+
PrometheusExporter::Instrumentation::ActiveRecord.start(
|
225
|
+
custom_labels: { type: "unicorn_worker" }, #optional params
|
226
|
+
config_labels: [:database, :host] #optional params
|
227
|
+
)
|
228
|
+
end
|
229
|
+
```
|
230
|
+
|
231
|
+
For Sidekiq
|
232
|
+
```ruby
|
233
|
+
Sidekiq.configure_server do |config|
|
234
|
+
config.on :startup do
|
235
|
+
require 'prometheus_exporter/instrumentation'
|
236
|
+
PrometheusExporter::Instrumentation::ActiveRecord.start(
|
237
|
+
custom_labels: { type: "sidekiq" }, #optional params
|
238
|
+
config_labels: [:database, :host] #optional params
|
239
|
+
)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
```
|
243
|
+
|
178
244
|
#### Per-process stats
|
179
245
|
|
180
246
|
You may also be interested in per-process stats. This collects memory and GC stats:
|
@@ -4,16 +4,16 @@ require 'socket'
|
|
4
4
|
require 'thread'
|
5
5
|
|
6
6
|
module PrometheusExporter
|
7
|
-
|
8
7
|
class Client
|
9
8
|
class RemoteMetric
|
10
9
|
attr_reader :name, :type, :help
|
11
10
|
|
12
|
-
def initialize(name:, help:, type:, client:)
|
11
|
+
def initialize(name:, help:, type:, client:, opts: nil)
|
13
12
|
@name = name
|
14
13
|
@help = help
|
15
14
|
@client = client
|
16
15
|
@type = type
|
16
|
+
@opts = opts
|
17
17
|
end
|
18
18
|
|
19
19
|
def standard_values(value, keys, prometheus_exporter_action = nil)
|
@@ -25,6 +25,7 @@ module PrometheusExporter
|
|
25
25
|
value: value
|
26
26
|
}
|
27
27
|
values[:prometheus_exporter_action] = prometheus_exporter_action if prometheus_exporter_action
|
28
|
+
values[:opts] = @opts if @opts
|
28
29
|
values
|
29
30
|
end
|
30
31
|
|
@@ -39,7 +40,6 @@ module PrometheusExporter
|
|
39
40
|
def decrement(keys = nil, value = 1)
|
40
41
|
@client.send_json(standard_values(value, keys, :decrement))
|
41
42
|
end
|
42
|
-
|
43
43
|
end
|
44
44
|
|
45
45
|
def self.default
|
@@ -83,8 +83,8 @@ module PrometheusExporter
|
|
83
83
|
@custom_labels = custom_labels
|
84
84
|
end
|
85
85
|
|
86
|
-
def register(type, name, help)
|
87
|
-
metric = RemoteMetric.new(type: type, name: name, help: help, client: self)
|
86
|
+
def register(type, name, help, opts = nil)
|
87
|
+
metric = RemoteMetric.new(type: type, name: name, help: help, client: self, opts: opts)
|
88
88
|
@metrics << metric
|
89
89
|
metric
|
90
90
|
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# collects stats from currently running process
|
4
|
+
module PrometheusExporter::Instrumentation
|
5
|
+
class ActiveRecord
|
6
|
+
ALLOWED_CONFIG_LABELS = %i(database username host port)
|
7
|
+
|
8
|
+
def self.start(client: nil, frequency: 30, custom_labels: {}, config_labels: [])
|
9
|
+
|
10
|
+
# Not all rails versions support coonection pool stats
|
11
|
+
unless ::ActiveRecord::Base.connection_pool.respond_to?(:stat)
|
12
|
+
STDERR.puts("ActiveRecord connection pool stats not supported in your rails version")
|
13
|
+
return
|
14
|
+
end
|
15
|
+
|
16
|
+
config_labels.map!(&:to_sym)
|
17
|
+
validate_config_labels(config_labels)
|
18
|
+
|
19
|
+
active_record_collector = new(custom_labels, config_labels)
|
20
|
+
|
21
|
+
client ||= PrometheusExporter::Client.default
|
22
|
+
|
23
|
+
stop if @thread
|
24
|
+
|
25
|
+
@thread = Thread.new do
|
26
|
+
while true
|
27
|
+
begin
|
28
|
+
metrics = active_record_collector.collect
|
29
|
+
metrics.each { |metric| client.send_json metric }
|
30
|
+
rescue => e
|
31
|
+
STDERR.puts("Prometheus Exporter Failed To Collect Process Stats #{e}")
|
32
|
+
ensure
|
33
|
+
sleep frequency
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.validate_config_labels(config_labels)
|
40
|
+
return if config_labels.size == 0
|
41
|
+
raise "Invalid Config Labels, available options #{ALLOWED_CONFIG_LABELS}" if (config_labels - ALLOWED_CONFIG_LABELS).size > 0
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.stop
|
45
|
+
if t = @thread
|
46
|
+
t.kill
|
47
|
+
@thread = nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def initialize(metric_labels, config_labels)
|
52
|
+
@metric_labels = metric_labels
|
53
|
+
@config_labels = config_labels
|
54
|
+
@hostname = nil
|
55
|
+
end
|
56
|
+
|
57
|
+
def hostname
|
58
|
+
@hostname ||=
|
59
|
+
begin
|
60
|
+
`hostname`.strip
|
61
|
+
rescue => e
|
62
|
+
STDERR.puts "Unable to lookup hostname #{e}"
|
63
|
+
"unknown-host"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def collect
|
68
|
+
metrics = []
|
69
|
+
collect_active_record_pool_stats(metrics)
|
70
|
+
metrics
|
71
|
+
end
|
72
|
+
|
73
|
+
def pid
|
74
|
+
@pid = ::Process.pid
|
75
|
+
end
|
76
|
+
|
77
|
+
def collect_active_record_pool_stats(metrics)
|
78
|
+
ObjectSpace.each_object(::ActiveRecord::ConnectionAdapters::ConnectionPool) do |pool|
|
79
|
+
next if pool.connections.nil?
|
80
|
+
|
81
|
+
labels_from_config = pool.spec.config
|
82
|
+
.select { |k, v| @config_labels.include? k }
|
83
|
+
.map { |k, v| [k.to_s.prepend("dbconfig_"), v] }
|
84
|
+
|
85
|
+
labels = @metric_labels.merge(pool_name: pool.spec.name).merge(Hash[labels_from_config])
|
86
|
+
|
87
|
+
metric = {
|
88
|
+
pid: pid,
|
89
|
+
type: "active_record",
|
90
|
+
hostname: hostname,
|
91
|
+
metric_labels: labels
|
92
|
+
}
|
93
|
+
metric.merge!(pool.stat)
|
94
|
+
metrics << metric
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -13,7 +13,9 @@ module PrometheusExporter::Instrumentation
|
|
13
13
|
callbacks do |lifecycle|
|
14
14
|
lifecycle.around(:invoke_job) do |job, *args, &block|
|
15
15
|
max_attempts = Delayed::Worker.max_attempts
|
16
|
-
|
16
|
+
enqueued_count = Delayed::Job.count
|
17
|
+
pending_count = Delayed::Job.where(attempts: 0, locked_at: nil).count
|
18
|
+
instrumenter.call(job, max_attempts, enqueued_count, pending_count, *args, &block)
|
17
19
|
end
|
18
20
|
end
|
19
21
|
end
|
@@ -26,7 +28,7 @@ module PrometheusExporter::Instrumentation
|
|
26
28
|
@client = client || PrometheusExporter::Client.default
|
27
29
|
end
|
28
30
|
|
29
|
-
def call(job, max_attempts, *args, &block)
|
31
|
+
def call(job, max_attempts, enqueued_count, pending_count, *args, &block)
|
30
32
|
success = false
|
31
33
|
start = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
32
34
|
attempts = job.attempts + 1 # Increment because we're adding the current attempt
|
@@ -42,7 +44,9 @@ module PrometheusExporter::Instrumentation
|
|
42
44
|
success: success,
|
43
45
|
duration: duration,
|
44
46
|
attempts: attempts,
|
45
|
-
max_attempts: max_attempts
|
47
|
+
max_attempts: max_attempts,
|
48
|
+
enqueued: enqueued_count,
|
49
|
+
pending: pending_count
|
46
50
|
)
|
47
51
|
end
|
48
52
|
end
|
@@ -9,7 +9,7 @@ end
|
|
9
9
|
module PrometheusExporter::Instrumentation
|
10
10
|
# collects stats from unicorn
|
11
11
|
class Unicorn
|
12
|
-
def self.start(pid_file:, listener_address:, client
|
12
|
+
def self.start(pid_file:, listener_address:, client: nil, frequency: 30)
|
13
13
|
unicorn_collector = new(pid_file: pid_file, listener_address: listener_address)
|
14
14
|
client ||= PrometheusExporter::Client.default
|
15
15
|
Thread.new do
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PrometheusExporter::Server
|
4
|
+
class ActiveRecordCollector < TypeCollector
|
5
|
+
MAX_ACTIVERECORD_METRIC_AGE = 60
|
6
|
+
ACTIVE_RECORD_GAUGES = {
|
7
|
+
connections: "Total connections in pool",
|
8
|
+
busy: "Connections in use in pool",
|
9
|
+
dead: "Dead connections in pool",
|
10
|
+
idle: "Idle connections in pool",
|
11
|
+
waiting: "Connection requests waiting",
|
12
|
+
size: "Maximum allowed connection pool size"
|
13
|
+
}
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@active_record_metrics = []
|
17
|
+
end
|
18
|
+
|
19
|
+
def type
|
20
|
+
"active_record"
|
21
|
+
end
|
22
|
+
|
23
|
+
def metrics
|
24
|
+
return [] if @active_record_metrics.length == 0
|
25
|
+
|
26
|
+
metrics = {}
|
27
|
+
|
28
|
+
@active_record_metrics.map do |m|
|
29
|
+
metric_key = (m["metric_labels"] || {}).merge("pid" => m["pid"])
|
30
|
+
|
31
|
+
ACTIVE_RECORD_GAUGES.map do |k, help|
|
32
|
+
k = k.to_s
|
33
|
+
if v = m[k]
|
34
|
+
g = metrics[k] ||= PrometheusExporter::Metric::Gauge.new("active_record_connection_pool_#{k}", help)
|
35
|
+
g.observe(v, metric_key)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
metrics.values
|
41
|
+
end
|
42
|
+
|
43
|
+
def collect(obj)
|
44
|
+
now = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
45
|
+
|
46
|
+
obj["created_at"] = now
|
47
|
+
|
48
|
+
@active_record_metrics.delete_if do |current|
|
49
|
+
(obj["pid"] == current["pid"] && obj["hostname"] == current["hostname"]) ||
|
50
|
+
(current["created_at"] + MAX_ACTIVERECORD_METRIC_AGE < now)
|
51
|
+
end
|
52
|
+
|
53
|
+
@active_record_metrics << obj
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -17,6 +17,7 @@ module PrometheusExporter::Server
|
|
17
17
|
register_collector(PumaCollector.new)
|
18
18
|
register_collector(HutchCollector.new)
|
19
19
|
register_collector(UnicornCollector.new)
|
20
|
+
register_collector(ActiveRecordCollector.new)
|
20
21
|
end
|
21
22
|
|
22
23
|
def register_collector(collector)
|
@@ -72,6 +73,7 @@ module PrometheusExporter::Server
|
|
72
73
|
def register_metric_unsafe(obj)
|
73
74
|
name = obj["name"]
|
74
75
|
help = obj["help"]
|
76
|
+
opts = symbolize_keys(obj["opts"] || {})
|
75
77
|
|
76
78
|
metric =
|
77
79
|
case obj["type"]
|
@@ -80,9 +82,9 @@ module PrometheusExporter::Server
|
|
80
82
|
when "counter"
|
81
83
|
PrometheusExporter::Metric::Counter.new(name, help)
|
82
84
|
when "summary"
|
83
|
-
PrometheusExporter::Metric::Summary.new(name, help)
|
85
|
+
PrometheusExporter::Metric::Summary.new(name, help, opts)
|
84
86
|
when "histogram"
|
85
|
-
PrometheusExporter::Metric::Histogram.new(name, help)
|
87
|
+
PrometheusExporter::Metric::Histogram.new(name, help, opts)
|
86
88
|
end
|
87
89
|
|
88
90
|
if metric
|
@@ -91,5 +93,9 @@ module PrometheusExporter::Server
|
|
91
93
|
STDERR.puts "failed to register metric #{obj}"
|
92
94
|
end
|
93
95
|
end
|
96
|
+
|
97
|
+
def symbolize_keys(hash)
|
98
|
+
hash.inject({}) { |memo, k| memo[k.first.to_sym] = k.last; memo }
|
99
|
+
end
|
94
100
|
end
|
95
101
|
end
|
@@ -21,12 +21,15 @@ module PrometheusExporter::Server
|
|
21
21
|
@delayed_job_duration_seconds_summary.observe(obj["duration"], status: "success") if obj["success"]
|
22
22
|
@delayed_job_duration_seconds_summary.observe(obj["duration"], status: "failed") if !obj["success"]
|
23
23
|
@delayed_job_attempts_summary.observe(obj["attempts"]) if obj["success"]
|
24
|
+
@delayed_jobs_enqueued.observe(obj["enqueued"])
|
25
|
+
@delayed_jobs_pending.observe(obj["pending"])
|
24
26
|
end
|
25
27
|
|
26
28
|
def metrics
|
27
29
|
if @delayed_jobs_total
|
28
30
|
[@delayed_job_duration_seconds, @delayed_jobs_total, @delayed_failed_jobs_total,
|
29
|
-
@delayed_jobs_max_attempts_reached_total, @delayed_job_duration_seconds_summary, @delayed_job_attempts_summary
|
31
|
+
@delayed_jobs_max_attempts_reached_total, @delayed_job_duration_seconds_summary, @delayed_job_attempts_summary,
|
32
|
+
@delayed_jobs_enqueued, @delayed_jobs_pending]
|
30
33
|
else
|
31
34
|
[]
|
32
35
|
end
|
@@ -45,6 +48,14 @@ module PrometheusExporter::Server
|
|
45
48
|
PrometheusExporter::Metric::Counter.new(
|
46
49
|
"delayed_jobs_total", "Total number of delayed jobs executed.")
|
47
50
|
|
51
|
+
@delayed_jobs_enqueued =
|
52
|
+
PrometheusExporter::Metric::Gauge.new(
|
53
|
+
"delayed_jobs_enqueued", "Number of enqueued delayed jobs.")
|
54
|
+
|
55
|
+
@delayed_jobs_pending =
|
56
|
+
PrometheusExporter::Metric::Gauge.new(
|
57
|
+
"delayed_jobs_pending", "Number of pending delayed jobs.")
|
58
|
+
|
48
59
|
@delayed_failed_jobs_total =
|
49
60
|
PrometheusExporter::Metric::Counter.new(
|
50
61
|
"delayed_failed_jobs_total", "Total number failed delayed jobs executed.")
|
@@ -25,11 +25,13 @@ class PrometheusExporter::Server::UnicornCollector < PrometheusExporter::Server:
|
|
25
25
|
metrics = {}
|
26
26
|
|
27
27
|
@unicorn_metrics.map do |m|
|
28
|
+
labels = m["custom_labels"] || {}
|
29
|
+
|
28
30
|
UNICORN_GAUGES.map do |k, help|
|
29
31
|
k = k.to_s
|
30
32
|
if (v = m[k])
|
31
33
|
g = metrics[k] ||= PrometheusExporter::Metric::Gauge.new("unicorn_#{k}", help)
|
32
|
-
g.observe(v)
|
34
|
+
g.observe(v, labels)
|
33
35
|
end
|
34
36
|
end
|
35
37
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prometheus_exporter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Saffron
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-11-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rubocop
|
@@ -174,6 +174,7 @@ files:
|
|
174
174
|
- lib/prometheus_exporter.rb
|
175
175
|
- lib/prometheus_exporter/client.rb
|
176
176
|
- lib/prometheus_exporter/instrumentation.rb
|
177
|
+
- lib/prometheus_exporter/instrumentation/active_record.rb
|
177
178
|
- lib/prometheus_exporter/instrumentation/delayed_job.rb
|
178
179
|
- lib/prometheus_exporter/instrumentation/hutch.rb
|
179
180
|
- lib/prometheus_exporter/instrumentation/method_profiler.rb
|
@@ -189,6 +190,7 @@ files:
|
|
189
190
|
- lib/prometheus_exporter/metric/summary.rb
|
190
191
|
- lib/prometheus_exporter/middleware.rb
|
191
192
|
- lib/prometheus_exporter/server.rb
|
193
|
+
- lib/prometheus_exporter/server/active_record_collector.rb
|
192
194
|
- lib/prometheus_exporter/server/collector.rb
|
193
195
|
- lib/prometheus_exporter/server/collector_base.rb
|
194
196
|
- lib/prometheus_exporter/server/delayed_job_collector.rb
|