prometheus_exporter 2.1.0 → 2.2.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 +4 -4
- data/.github/workflows/ci.yml +10 -6
- data/.rubocop +1 -0
- data/.rubocop.yml +12 -1
- data/.streerc +2 -0
- data/CHANGELOG +12 -1
- data/README.md +22 -9
- data/bench/bench.rb +12 -11
- data/bin/prometheus_exporter +2 -2
- data/examples/custom_collector.rb +1 -3
- data/gemfiles/ar_70.gemfile +2 -0
- data/gemfiles/ar_71.gemfile +7 -0
- data/lib/prometheus_exporter/client.rb +16 -32
- data/lib/prometheus_exporter/instrumentation/active_record.rb +20 -8
- data/lib/prometheus_exporter/instrumentation/delayed_job.rb +23 -13
- data/lib/prometheus_exporter/instrumentation/good_job.rb +2 -4
- data/lib/prometheus_exporter/instrumentation/hutch.rb +1 -1
- data/lib/prometheus_exporter/instrumentation/method_profiler.rb +16 -16
- data/lib/prometheus_exporter/instrumentation/periodic_stats.rb +13 -21
- data/lib/prometheus_exporter/instrumentation/process.rb +14 -6
- data/lib/prometheus_exporter/instrumentation/puma.rb +1 -1
- data/lib/prometheus_exporter/instrumentation/resque.rb +1 -3
- data/lib/prometheus_exporter/instrumentation/shoryuken.rb +6 -7
- data/lib/prometheus_exporter/instrumentation/sidekiq.rb +4 -6
- data/lib/prometheus_exporter/instrumentation/sidekiq_process.rb +12 -19
- data/lib/prometheus_exporter/instrumentation/sidekiq_queue.rb +15 -18
- data/lib/prometheus_exporter/instrumentation/sidekiq_stats.rb +10 -15
- data/lib/prometheus_exporter/instrumentation/unicorn.rb +2 -2
- data/lib/prometheus_exporter/metric/base.rb +8 -7
- data/lib/prometheus_exporter/metric/counter.rb +1 -3
- data/lib/prometheus_exporter/metric/gauge.rb +2 -6
- data/lib/prometheus_exporter/metric/histogram.rb +0 -2
- data/lib/prometheus_exporter/metric/summary.rb +5 -14
- data/lib/prometheus_exporter/middleware.rb +40 -32
- data/lib/prometheus_exporter/server/active_record_collector.rb +11 -6
- data/lib/prometheus_exporter/server/collector.rb +12 -16
- data/lib/prometheus_exporter/server/collector_base.rb +0 -2
- data/lib/prometheus_exporter/server/delayed_job_collector.rb +65 -28
- data/lib/prometheus_exporter/server/good_job_collector.rb +1 -1
- data/lib/prometheus_exporter/server/hutch_collector.rb +19 -11
- data/lib/prometheus_exporter/server/metrics_container.rb +4 -4
- data/lib/prometheus_exporter/server/process_collector.rb +7 -3
- data/lib/prometheus_exporter/server/puma_collector.rb +4 -10
- data/lib/prometheus_exporter/server/resque_collector.rb +1 -1
- data/lib/prometheus_exporter/server/runner.rb +34 -13
- data/lib/prometheus_exporter/server/shoryuken_collector.rb +22 -17
- data/lib/prometheus_exporter/server/sidekiq_collector.rb +22 -14
- data/lib/prometheus_exporter/server/sidekiq_process_collector.rb +9 -5
- data/lib/prometheus_exporter/server/sidekiq_queue_collector.rb +7 -6
- data/lib/prometheus_exporter/server/sidekiq_stats_collector.rb +12 -11
- data/lib/prometheus_exporter/server/unicorn_collector.rb +4 -4
- data/lib/prometheus_exporter/server/web_collector.rb +39 -22
- data/lib/prometheus_exporter/server/web_server.rb +10 -20
- data/lib/prometheus_exporter/version.rb +1 -1
- data/prometheus_exporter.gemspec +20 -22
- metadata +44 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e8f8c9307f755aa00e95f323d2be11cdf6830f7e420c9bf70d90260e9bc81a85
|
4
|
+
data.tar.gz: 216bedbba838f0a84391ef2e85b290aa596cf3c42d27b4cc6bce7a9fae8be01d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3ad534e47314779c76eb9e80d5de23619cd0865c2337147188d7f2ddba3bff9a6c9cf630e20720899c4e7ef9c95bf1db317a719d08fc241850f902aceae1b5cf
|
7
|
+
data.tar.gz: 6e71eab8cf6cdb049612c5afc404d6e399a142ee3eb5bbb3ae897e374ac6474d09f1b6c3ad94ab31f8d12fc52fc9e609a8b066051c89e44ea84be0fa0ec2cf0e
|
data/.github/workflows/ci.yml
CHANGED
@@ -27,20 +27,24 @@ jobs:
|
|
27
27
|
strategy:
|
28
28
|
fail-fast: false
|
29
29
|
matrix:
|
30
|
-
ruby: [
|
31
|
-
activerecord: [
|
30
|
+
ruby: ["3.1", "3.2", "3.3"]
|
31
|
+
activerecord: [61, 70, 71]
|
32
32
|
|
33
33
|
steps:
|
34
|
-
- uses: actions/checkout@
|
34
|
+
- uses: actions/checkout@v4
|
35
35
|
|
36
36
|
- uses: ruby/setup-ruby@v1
|
37
37
|
with:
|
38
38
|
ruby-version: ${{ matrix.ruby }}
|
39
|
+
bundler: latest
|
39
40
|
bundler-cache: true
|
40
41
|
|
41
42
|
- name: Rubocop
|
42
43
|
run: bundle exec rubocop
|
43
44
|
|
45
|
+
- name: Syntax tree
|
46
|
+
run: bundle exec stree check Gemfile $(git ls-files '*.rb') $(git ls-files '*.rake') $(git ls-files '*.thor')
|
47
|
+
|
44
48
|
- name: Run tests
|
45
49
|
run: bundle exec rake
|
46
50
|
|
@@ -50,10 +54,10 @@ jobs:
|
|
50
54
|
runs-on: ubuntu-latest
|
51
55
|
|
52
56
|
outputs:
|
53
|
-
new_version_published: ${{ steps.release.outputs.
|
57
|
+
new_version_published: ${{ steps.release.outputs.new_version }}
|
54
58
|
|
55
59
|
steps:
|
56
|
-
- uses: actions/checkout@
|
60
|
+
- uses: actions/checkout@v4
|
57
61
|
|
58
62
|
- name: Release gem
|
59
63
|
id: release
|
@@ -70,7 +74,7 @@ jobs:
|
|
70
74
|
timeout-minutes: 20
|
71
75
|
|
72
76
|
steps:
|
73
|
-
- uses: actions/checkout@
|
77
|
+
- uses: actions/checkout@v4
|
74
78
|
- uses: docker/setup-qemu-action@v2
|
75
79
|
- uses: docker/setup-buildx-action@v2
|
76
80
|
|
data/.rubocop
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--ignore-unrecognized-cops
|
data/.rubocop.yml
CHANGED
@@ -4,4 +4,15 @@ inherit_gem:
|
|
4
4
|
AllCops:
|
5
5
|
Exclude:
|
6
6
|
- 'gemfiles/**/*'
|
7
|
-
- 'vendor/**/*'
|
7
|
+
- 'vendor/**/*'
|
8
|
+
|
9
|
+
Discourse/Plugins/NoMonkeyPatching:
|
10
|
+
Enabled: false
|
11
|
+
|
12
|
+
Discourse/Plugins/NamespaceMethods:
|
13
|
+
Exclude:
|
14
|
+
- bin/prometheus_exporter
|
15
|
+
|
16
|
+
Style/InvertibleUnlessCondition:
|
17
|
+
Exclude:
|
18
|
+
- '*.gemspec'
|
data/.streerc
ADDED
data/CHANGELOG
CHANGED
@@ -1,4 +1,15 @@
|
|
1
|
-
2.
|
1
|
+
2.2.0 - 2024-12-05
|
2
|
+
|
3
|
+
- FIX: Ensure socket is closed when error is raised while opening socket
|
4
|
+
- Feature: Add Dalli::Client memcache metrics for web_collector
|
5
|
+
|
6
|
+
2.1.1 - 2024-06-19
|
7
|
+
|
8
|
+
- FEATURE: improve good_job instrumentation
|
9
|
+
- FIX: improve Ruby 3.X support
|
10
|
+
- FEATURE: imstrumentation for malloc / oldmalloc increace in GC stats
|
11
|
+
|
12
|
+
2.1.0 - 2024-01-08
|
2
13
|
|
3
14
|
- FEATURE: good_job instrumentation
|
4
15
|
- PERF: improve performance of histogram
|
data/README.md
CHANGED
@@ -40,7 +40,7 @@ To learn more see [Instrumenting Rails with Prometheus](https://samsaffron.com/a
|
|
40
40
|
|
41
41
|
## Requirements
|
42
42
|
|
43
|
-
Minimum Ruby of version
|
43
|
+
Minimum Ruby of version 3.0.0 is required, Ruby 2.7 is EOL as of March 31st 2023.
|
44
44
|
|
45
45
|
## Migrating from v0.x
|
46
46
|
|
@@ -213,13 +213,14 @@ Rails.application.middleware.unshift PrometheusExporter::Middleware, instrument:
|
|
213
213
|
|
214
214
|
#### Metrics collected by Rails integration middleware
|
215
215
|
|
216
|
-
| Type | Name
|
217
|
-
| --- | ---
|
218
|
-
| Counter | `http_requests_total`
|
219
|
-
| Summary | `http_request_duration_seconds`
|
220
|
-
| Summary | `http_request_redis_duration_seconds`¹
|
221
|
-
| Summary | `http_request_sql_duration_seconds`²
|
222
|
-
| Summary | `http_request_queue_duration_seconds`³
|
216
|
+
| Type | Name | Description |
|
217
|
+
| --- | --- | --- |
|
218
|
+
| Counter | `http_requests_total` | Total HTTP requests from web app |
|
219
|
+
| Summary | `http_request_duration_seconds` | Time spent in HTTP reqs in seconds |
|
220
|
+
| Summary | `http_request_redis_duration_seconds`¹ | Time spent in HTTP reqs in Redis, in seconds |
|
221
|
+
| Summary | `http_request_sql_duration_seconds`² | Time spent in HTTP reqs in SQL in seconds |
|
222
|
+
| Summary | `http_request_queue_duration_seconds`³ | Time spent queueing the request in load balancer in seconds |
|
223
|
+
| Summary | `http_request_memcache_duration_seconds`⁴ | Time spent in HTTP reqs in Memcache in seconds |
|
223
224
|
|
224
225
|
All metrics have a `controller` and an `action` label.
|
225
226
|
`http_requests_total` additionally has a (HTTP response) `status` label.
|
@@ -268,6 +269,7 @@ ruby_http_request_duration_seconds{path="/api/v1/teams/:id",method="GET",status=
|
|
268
269
|
¹) Only available when Redis is used.
|
269
270
|
²) Only available when Mysql or PostgreSQL are used.
|
270
271
|
³) Only available when [Instrumenting Request Queueing Time](#instrumenting-request-queueing-time) is set up.
|
272
|
+
⁴) Only available when Dalli is used.
|
271
273
|
|
272
274
|
#### Activerecord Connection Pool Metrics
|
273
275
|
|
@@ -583,6 +585,17 @@ The puma metrics are using the `Puma.stats` method and hence need to be started
|
|
583
585
|
workers has been booted and from a Puma thread otherwise the metrics won't be accessible.
|
584
586
|
The easiest way to gather this metrics is to put the following in your `puma.rb` config:
|
585
587
|
|
588
|
+
For Puma single mode
|
589
|
+
```ruby
|
590
|
+
# puma.rb config
|
591
|
+
require 'prometheus_exporter/instrumentation'
|
592
|
+
# optional check, avoids spinning up and down threads per worker
|
593
|
+
if !PrometheusExporter::Instrumentation::Puma.started?
|
594
|
+
PrometheusExporter::Instrumentation::Puma.start
|
595
|
+
end
|
596
|
+
```
|
597
|
+
|
598
|
+
For Puma clustered mode
|
586
599
|
```ruby
|
587
600
|
# puma.rb config
|
588
601
|
after_worker_boot do
|
@@ -884,7 +897,7 @@ prometheus_exporter -p 8080 \
|
|
884
897
|
--prefix 'foo_'
|
885
898
|
```
|
886
899
|
|
887
|
-
You can use `-b` option to bind the `prometheus_exporter` web server to any IPv4 interface with `-b 0.0.0.0`,
|
900
|
+
You can use `-b` option to bind the `prometheus_exporter` web server to any IPv4 interface with `-b 0.0.0.0`,
|
888
901
|
any IPv6 interface with `-b ::`, or `-b ANY` to any IPv4/IPv6 interfaces available on your host system.
|
889
902
|
|
890
903
|
#### Enabling Basic Authentication
|
data/bench/bench.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
require_relative
|
3
|
+
require_relative "../lib/prometheus_exporter"
|
4
|
+
require_relative "../lib/prometheus_exporter/client"
|
5
|
+
require_relative "../lib/prometheus_exporter/server"
|
6
6
|
|
7
7
|
# test how long it takes a custom collector to process 10k messages
|
8
8
|
|
@@ -26,18 +26,19 @@ end
|
|
26
26
|
@client = nil
|
27
27
|
@runs = 1000
|
28
28
|
|
29
|
-
done =
|
30
|
-
|
31
|
-
|
32
|
-
@
|
33
|
-
|
29
|
+
done =
|
30
|
+
lambda do
|
31
|
+
puts "Elapsed for 10k messages is #{Time.now - @start}"
|
32
|
+
if (@runs -= 1) > 0
|
33
|
+
@start = Time.now
|
34
|
+
10_000.times { @client.send_json(hello: "world") }
|
35
|
+
end
|
34
36
|
end
|
35
|
-
end
|
36
37
|
|
37
38
|
collector = Collector.new(done)
|
38
|
-
server = PrometheusExporter::Server::WebServer.new port:
|
39
|
+
server = PrometheusExporter::Server::WebServer.new port: 12_349, collector: collector
|
39
40
|
server.start
|
40
|
-
@client = PrometheusExporter::Client.new port:
|
41
|
+
@client = PrometheusExporter::Client.new port: 12_349, max_queue_size: 100_000
|
41
42
|
|
42
43
|
@start = Time.now
|
43
44
|
10_000.times { @client.send_json(hello: "world") }
|
data/bin/prometheus_exporter
CHANGED
@@ -74,7 +74,7 @@ def run
|
|
74
74
|
end.parse!
|
75
75
|
|
76
76
|
logger = Logger.new(options[:logger_path])
|
77
|
-
logger.level = Logger::
|
77
|
+
logger.level = Logger::INFO
|
78
78
|
|
79
79
|
if options.has_key?(:realm) && !options.has_key?(:auth)
|
80
80
|
logger.warn "Providing REALM without AUTH has no effect"
|
@@ -121,7 +121,7 @@ def run
|
|
121
121
|
|
122
122
|
runner = PrometheusExporter::Server::Runner.new(options)
|
123
123
|
|
124
|
-
|
124
|
+
logger.info "Starting prometheus exporter on #{runner.bind}:#{runner.port}"
|
125
125
|
runner.start
|
126
126
|
sleep
|
127
127
|
end
|
@@ -20,8 +20,6 @@ class MyCustomCollector < PrometheusExporter::Server::BaseCollector
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def prometheus_metrics_text
|
23
|
-
@mutex.synchronize
|
24
|
-
"#{@gauge1.to_prometheus_text}\n#{@gauge2.to_prometheus_text}"
|
25
|
-
end
|
23
|
+
@mutex.synchronize { "#{@gauge1.to_prometheus_text}\n#{@gauge2.to_prometheus_text}" }
|
26
24
|
end
|
27
25
|
end
|
data/gemfiles/ar_70.gemfile
CHANGED
@@ -17,13 +17,7 @@ module PrometheusExporter
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def standard_values(value, keys, prometheus_exporter_action = nil)
|
20
|
-
values = {
|
21
|
-
type: @type,
|
22
|
-
help: @help,
|
23
|
-
name: @name,
|
24
|
-
keys: keys,
|
25
|
-
value: value
|
26
|
-
}
|
20
|
+
values = { type: @type, help: @help, name: @name, keys: keys, value: value }
|
27
21
|
values[
|
28
22
|
:prometheus_exporter_action
|
29
23
|
] = prometheus_exporter_action if prometheus_exporter_action
|
@@ -59,16 +53,14 @@ module PrometheusExporter
|
|
59
53
|
|
60
54
|
def initialize(
|
61
55
|
host: ENV.fetch("PROMETHEUS_EXPORTER_HOST", "localhost"),
|
62
|
-
port: ENV.fetch(
|
63
|
-
"PROMETHEUS_EXPORTER_PORT",
|
64
|
-
PrometheusExporter::DEFAULT_PORT
|
65
|
-
),
|
56
|
+
port: ENV.fetch("PROMETHEUS_EXPORTER_PORT", PrometheusExporter::DEFAULT_PORT),
|
66
57
|
max_queue_size: nil,
|
67
58
|
thread_sleep: 0.5,
|
68
59
|
json_serializer: nil,
|
69
60
|
custom_labels: nil,
|
70
61
|
logger: Logger.new(STDERR),
|
71
|
-
log_level: Logger::WARN
|
62
|
+
log_level: Logger::WARN,
|
63
|
+
process_queue_once_and_stop: false
|
72
64
|
)
|
73
65
|
@logger = logger
|
74
66
|
@logger.level = log_level
|
@@ -83,9 +75,7 @@ module PrometheusExporter
|
|
83
75
|
max_queue_size ||= MAX_QUEUE_SIZE
|
84
76
|
max_queue_size = max_queue_size.to_i
|
85
77
|
|
86
|
-
if max_queue_size <= 0
|
87
|
-
raise ArgumentError, "max_queue_size must be larger than 0"
|
88
|
-
end
|
78
|
+
raise ArgumentError, "max_queue_size must be larger than 0" if max_queue_size <= 0
|
89
79
|
|
90
80
|
@max_queue_size = max_queue_size
|
91
81
|
@host = host
|
@@ -94,10 +84,10 @@ module PrometheusExporter
|
|
94
84
|
@mutex = Mutex.new
|
95
85
|
@thread_sleep = thread_sleep
|
96
86
|
|
97
|
-
@json_serializer =
|
98
|
-
json_serializer == :oj ? PrometheusExporter::OjCompat : JSON
|
87
|
+
@json_serializer = json_serializer == :oj ? PrometheusExporter::OjCompat : JSON
|
99
88
|
|
100
89
|
@custom_labels = custom_labels
|
90
|
+
@process_queue_once_and_stop = process_queue_once_and_stop
|
101
91
|
end
|
102
92
|
|
103
93
|
def custom_labels=(custom_labels)
|
@@ -105,14 +95,7 @@ module PrometheusExporter
|
|
105
95
|
end
|
106
96
|
|
107
97
|
def register(type, name, help, opts = nil)
|
108
|
-
metric =
|
109
|
-
RemoteMetric.new(
|
110
|
-
type: type,
|
111
|
-
name: name,
|
112
|
-
help: help,
|
113
|
-
client: self,
|
114
|
-
opts: opts
|
115
|
-
)
|
98
|
+
metric = RemoteMetric.new(type: type, name: name, help: help, client: self, opts: opts)
|
116
99
|
@metrics << metric
|
117
100
|
metric
|
118
101
|
end
|
@@ -163,7 +146,7 @@ module PrometheusExporter
|
|
163
146
|
@socket.write("\r\n")
|
164
147
|
rescue => e
|
165
148
|
logger.warn "Prometheus Exporter is dropping a message: #{e}"
|
166
|
-
|
149
|
+
close_socket!
|
167
150
|
raise
|
168
151
|
end
|
169
152
|
end
|
@@ -189,6 +172,11 @@ module PrometheusExporter
|
|
189
172
|
end
|
190
173
|
|
191
174
|
def ensure_worker_thread!
|
175
|
+
if @process_queue_once_and_stop
|
176
|
+
worker_loop
|
177
|
+
return
|
178
|
+
end
|
179
|
+
|
192
180
|
unless @worker_thread&.alive?
|
193
181
|
@mutex.synchronize do
|
194
182
|
return if @worker_thread&.alive?
|
@@ -253,8 +241,7 @@ module PrometheusExporter
|
|
253
241
|
|
254
242
|
nil
|
255
243
|
rescue StandardError
|
256
|
-
|
257
|
-
@socket_started = nil
|
244
|
+
close_socket!
|
258
245
|
@socket_pid = nil
|
259
246
|
raise
|
260
247
|
end
|
@@ -262,10 +249,7 @@ module PrometheusExporter
|
|
262
249
|
def wait_for_empty_queue_with_timeout(timeout_seconds)
|
263
250
|
start_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
264
251
|
while @queue.length > 0
|
265
|
-
if start_time + timeout_seconds <
|
266
|
-
::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
267
|
-
break
|
268
|
-
end
|
252
|
+
break if start_time + timeout_seconds < ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
269
253
|
sleep(0.05)
|
270
254
|
end
|
271
255
|
end
|
@@ -3,14 +3,16 @@
|
|
3
3
|
# collects stats from currently running process
|
4
4
|
module PrometheusExporter::Instrumentation
|
5
5
|
class ActiveRecord < PeriodicStats
|
6
|
-
ALLOWED_CONFIG_LABELS = %i
|
6
|
+
ALLOWED_CONFIG_LABELS = %i[database username host port]
|
7
7
|
|
8
8
|
def self.start(client: nil, frequency: 30, custom_labels: {}, config_labels: [])
|
9
9
|
client ||= PrometheusExporter::Client.default
|
10
10
|
|
11
11
|
# Not all rails versions support connection pool stats
|
12
12
|
unless ::ActiveRecord::Base.connection_pool.respond_to?(:stat)
|
13
|
-
client.logger.error(
|
13
|
+
client.logger.error(
|
14
|
+
"ActiveRecord connection pool stats not supported in your rails version",
|
15
|
+
)
|
14
16
|
return
|
15
17
|
end
|
16
18
|
|
@@ -29,7 +31,9 @@ module PrometheusExporter::Instrumentation
|
|
29
31
|
|
30
32
|
def self.validate_config_labels(config_labels)
|
31
33
|
return if config_labels.size == 0
|
32
|
-
|
34
|
+
if (config_labels - ALLOWED_CONFIG_LABELS).size > 0
|
35
|
+
raise "Invalid Config Labels, available options #{ALLOWED_CONFIG_LABELS}"
|
36
|
+
end
|
33
37
|
end
|
34
38
|
|
35
39
|
def initialize(metric_labels, config_labels)
|
@@ -55,7 +59,7 @@ module PrometheusExporter::Instrumentation
|
|
55
59
|
pid: pid,
|
56
60
|
type: "active_record",
|
57
61
|
hostname: ::PrometheusExporter.hostname,
|
58
|
-
metric_labels: labels(pool)
|
62
|
+
metric_labels: labels(pool),
|
59
63
|
}
|
60
64
|
metric.merge!(pool.stat)
|
61
65
|
metrics << metric
|
@@ -66,12 +70,20 @@ module PrometheusExporter::Instrumentation
|
|
66
70
|
|
67
71
|
def labels(pool)
|
68
72
|
if ::ActiveRecord.version < Gem::Version.new("6.1.0.rc1")
|
69
|
-
@metric_labels.merge(pool_name: pool.spec.name).merge(
|
70
|
-
|
71
|
-
|
73
|
+
@metric_labels.merge(pool_name: pool.spec.name).merge(
|
74
|
+
pool
|
75
|
+
.spec
|
76
|
+
.config
|
77
|
+
.select { |k, v| @config_labels.include? k }
|
78
|
+
.map { |k, v| [k.to_s.dup.prepend("dbconfig_"), v] }
|
79
|
+
.to_h,
|
80
|
+
)
|
72
81
|
else
|
73
82
|
@metric_labels.merge(pool_name: pool.db_config.name).merge(
|
74
|
-
@config_labels.each_with_object({})
|
83
|
+
@config_labels.each_with_object({}) do |l, acc|
|
84
|
+
acc["dbconfig_#{l}"] = pool.db_config.public_send(l)
|
85
|
+
end,
|
86
|
+
)
|
75
87
|
end
|
76
88
|
end
|
77
89
|
end
|
@@ -2,23 +2,33 @@
|
|
2
2
|
|
3
3
|
module PrometheusExporter::Instrumentation
|
4
4
|
class DelayedJob
|
5
|
-
JOB_CLASS_REGEXP =
|
5
|
+
JOB_CLASS_REGEXP = /job_class: ((\w+:{0,2})+)/.freeze
|
6
6
|
|
7
7
|
class << self
|
8
|
-
def register_plugin(client: nil)
|
8
|
+
def register_plugin(client: nil, include_module_name: false)
|
9
9
|
instrumenter = self.new(client: client)
|
10
10
|
return unless defined?(Delayed::Plugin)
|
11
11
|
|
12
|
-
plugin =
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
12
|
+
plugin =
|
13
|
+
Class.new(Delayed::Plugin) do
|
14
|
+
callbacks do |lifecycle|
|
15
|
+
lifecycle.around(:invoke_job) do |job, *args, &block|
|
16
|
+
max_attempts = Delayed::Worker.max_attempts
|
17
|
+
enqueued_count = Delayed::Job.where(queue: job.queue).count
|
18
|
+
pending_count =
|
19
|
+
Delayed::Job.where(attempts: 0, locked_at: nil, queue: job.queue).count
|
20
|
+
instrumenter.call(
|
21
|
+
job,
|
22
|
+
max_attempts,
|
23
|
+
enqueued_count,
|
24
|
+
pending_count,
|
25
|
+
include_module_name,
|
26
|
+
*args,
|
27
|
+
&block
|
28
|
+
)
|
29
|
+
end
|
19
30
|
end
|
20
31
|
end
|
21
|
-
end
|
22
32
|
|
23
33
|
Delayed::Worker.plugins << plugin
|
24
34
|
end
|
@@ -28,7 +38,7 @@ module PrometheusExporter::Instrumentation
|
|
28
38
|
@client = client || PrometheusExporter::Client.default
|
29
39
|
end
|
30
40
|
|
31
|
-
def call(job, max_attempts, enqueued_count, pending_count, *args, &block)
|
41
|
+
def call(job, max_attempts, enqueued_count, pending_count, include_module_name, *args, &block)
|
32
42
|
success = false
|
33
43
|
start = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
34
44
|
latency = Time.current - job.run_at
|
@@ -41,7 +51,7 @@ module PrometheusExporter::Instrumentation
|
|
41
51
|
|
42
52
|
@client.send_json(
|
43
53
|
type: "delayed_job",
|
44
|
-
name: job.handler.to_s.match(JOB_CLASS_REGEXP).to_a[1].to_s,
|
54
|
+
name: job.handler.to_s.match(JOB_CLASS_REGEXP).to_a[include_module_name ? 1 : 2].to_s,
|
45
55
|
queue_name: job.queue,
|
46
56
|
success: success,
|
47
57
|
duration: duration,
|
@@ -49,7 +59,7 @@ module PrometheusExporter::Instrumentation
|
|
49
59
|
attempts: attempts,
|
50
60
|
max_attempts: max_attempts,
|
51
61
|
enqueued: enqueued_count,
|
52
|
-
pending: pending_count
|
62
|
+
pending: pending_count,
|
53
63
|
)
|
54
64
|
end
|
55
65
|
end
|
@@ -7,9 +7,7 @@ module PrometheusExporter::Instrumentation
|
|
7
7
|
good_job_collector = new
|
8
8
|
client ||= PrometheusExporter::Client.default
|
9
9
|
|
10
|
-
worker_loop
|
11
|
-
client.send_json(good_job_collector.collect)
|
12
|
-
end
|
10
|
+
worker_loop { client.send_json(good_job_collector.collect) }
|
13
11
|
|
14
12
|
super
|
15
13
|
end
|
@@ -23,7 +21,7 @@ module PrometheusExporter::Instrumentation
|
|
23
21
|
running: ::GoodJob::Job.running.size,
|
24
22
|
finished: ::GoodJob::Job.finished.size,
|
25
23
|
succeeded: ::GoodJob::Job.succeeded.size,
|
26
|
-
discarded: ::GoodJob::Job.discarded.size
|
24
|
+
discarded: ::GoodJob::Job.discarded.size,
|
27
25
|
}
|
28
26
|
end
|
29
27
|
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# see https://samsaffron.com/archive/2017/10/18/fastest-way-to-profile-a-method-in-ruby
|
4
|
-
module PrometheusExporter::Instrumentation
|
4
|
+
module PrometheusExporter::Instrumentation
|
5
|
+
end
|
5
6
|
|
6
7
|
class PrometheusExporter::Instrumentation::MethodProfiler
|
7
8
|
def self.patch(klass, methods, name, instrument:)
|
@@ -21,9 +22,8 @@ class PrometheusExporter::Instrumentation::MethodProfiler
|
|
21
22
|
end
|
22
23
|
|
23
24
|
def self.start(transfer = nil)
|
24
|
-
Thread.current[:_method_profiler] = transfer ||
|
25
|
-
__start: Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
26
|
-
}
|
25
|
+
Thread.current[:_method_profiler] = transfer ||
|
26
|
+
{ __start: Process.clock_gettime(Process::CLOCK_MONOTONIC) }
|
27
27
|
end
|
28
28
|
|
29
29
|
def self.clear
|
@@ -42,9 +42,9 @@ class PrometheusExporter::Instrumentation::MethodProfiler
|
|
42
42
|
|
43
43
|
def self.define_methods_on_module(klass, methods, name)
|
44
44
|
patch_source_line = __LINE__ + 3
|
45
|
-
|
46
|
-
|
47
|
-
def #{method_name}(
|
45
|
+
|
46
|
+
patches = methods.map { |method_name| <<~RUBY }.join("\n")
|
47
|
+
def #{method_name}(...)
|
48
48
|
unless prof = Thread.current[:_method_profiler]
|
49
49
|
return super
|
50
50
|
end
|
@@ -58,9 +58,8 @@ class PrometheusExporter::Instrumentation::MethodProfiler
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
RUBY
|
61
|
-
end.join("\n")
|
62
61
|
|
63
|
-
klass.module_eval
|
62
|
+
klass.module_eval(patches, __FILE__, patch_source_line)
|
64
63
|
end
|
65
64
|
|
66
65
|
def self.patch_using_prepend(klass, methods, name)
|
@@ -71,17 +70,19 @@ class PrometheusExporter::Instrumentation::MethodProfiler
|
|
71
70
|
|
72
71
|
def self.patch_using_alias_method(klass, methods, name)
|
73
72
|
patch_source_line = __LINE__ + 3
|
74
|
-
|
75
|
-
|
73
|
+
|
74
|
+
patches = methods.map { |method_name| <<~RUBY }.join("\n")
|
76
75
|
unless defined?(#{method_name}__mp_unpatched)
|
77
76
|
alias_method :#{method_name}__mp_unpatched, :#{method_name}
|
78
|
-
|
77
|
+
|
78
|
+
def #{method_name}(...)
|
79
79
|
unless prof = Thread.current[:_method_profiler]
|
80
|
-
return #{method_name}__mp_unpatched(
|
80
|
+
return #{method_name}__mp_unpatched(...)
|
81
81
|
end
|
82
|
+
|
82
83
|
begin
|
83
84
|
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
84
|
-
#{method_name}__mp_unpatched(
|
85
|
+
#{method_name}__mp_unpatched(...)
|
85
86
|
ensure
|
86
87
|
data = (prof[:#{name}] ||= {duration: 0.0, calls: 0})
|
87
88
|
data[:duration] += Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
|
@@ -90,8 +91,7 @@ class PrometheusExporter::Instrumentation::MethodProfiler
|
|
90
91
|
end
|
91
92
|
end
|
92
93
|
RUBY
|
93
|
-
end.join("\n")
|
94
94
|
|
95
|
-
klass.class_eval
|
95
|
+
klass.class_eval(patches, __FILE__, patch_source_line)
|
96
96
|
end
|
97
97
|
end
|