prometheus_exporter 2.1.1 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +4 -1
  3. data/.streerc +2 -0
  4. data/CHANGELOG +5 -0
  5. data/README.md +9 -7
  6. data/bench/bench.rb +12 -11
  7. data/examples/custom_collector.rb +1 -3
  8. data/lib/prometheus_exporter/client.rb +16 -32
  9. data/lib/prometheus_exporter/instrumentation/active_record.rb +20 -8
  10. data/lib/prometheus_exporter/instrumentation/delayed_job.rb +20 -11
  11. data/lib/prometheus_exporter/instrumentation/good_job.rb +2 -4
  12. data/lib/prometheus_exporter/instrumentation/hutch.rb +1 -1
  13. data/lib/prometheus_exporter/instrumentation/method_profiler.rb +12 -12
  14. data/lib/prometheus_exporter/instrumentation/periodic_stats.rb +13 -21
  15. data/lib/prometheus_exporter/instrumentation/process.rb +12 -6
  16. data/lib/prometheus_exporter/instrumentation/puma.rb +1 -1
  17. data/lib/prometheus_exporter/instrumentation/resque.rb +1 -3
  18. data/lib/prometheus_exporter/instrumentation/shoryuken.rb +6 -7
  19. data/lib/prometheus_exporter/instrumentation/sidekiq.rb +4 -6
  20. data/lib/prometheus_exporter/instrumentation/sidekiq_process.rb +12 -19
  21. data/lib/prometheus_exporter/instrumentation/sidekiq_queue.rb +15 -18
  22. data/lib/prometheus_exporter/instrumentation/sidekiq_stats.rb +10 -15
  23. data/lib/prometheus_exporter/instrumentation/unicorn.rb +2 -2
  24. data/lib/prometheus_exporter/metric/base.rb +8 -7
  25. data/lib/prometheus_exporter/metric/counter.rb +1 -3
  26. data/lib/prometheus_exporter/metric/gauge.rb +2 -6
  27. data/lib/prometheus_exporter/metric/histogram.rb +0 -2
  28. data/lib/prometheus_exporter/metric/summary.rb +5 -14
  29. data/lib/prometheus_exporter/middleware.rb +40 -32
  30. data/lib/prometheus_exporter/server/active_record_collector.rb +11 -6
  31. data/lib/prometheus_exporter/server/collector.rb +12 -16
  32. data/lib/prometheus_exporter/server/collector_base.rb +0 -2
  33. data/lib/prometheus_exporter/server/delayed_job_collector.rb +65 -28
  34. data/lib/prometheus_exporter/server/good_job_collector.rb +1 -1
  35. data/lib/prometheus_exporter/server/hutch_collector.rb +19 -11
  36. data/lib/prometheus_exporter/server/metrics_container.rb +4 -4
  37. data/lib/prometheus_exporter/server/process_collector.rb +7 -5
  38. data/lib/prometheus_exporter/server/puma_collector.rb +4 -10
  39. data/lib/prometheus_exporter/server/resque_collector.rb +1 -1
  40. data/lib/prometheus_exporter/server/runner.rb +34 -13
  41. data/lib/prometheus_exporter/server/shoryuken_collector.rb +22 -17
  42. data/lib/prometheus_exporter/server/sidekiq_collector.rb +22 -14
  43. data/lib/prometheus_exporter/server/sidekiq_process_collector.rb +9 -5
  44. data/lib/prometheus_exporter/server/sidekiq_queue_collector.rb +7 -6
  45. data/lib/prometheus_exporter/server/sidekiq_stats_collector.rb +12 -11
  46. data/lib/prometheus_exporter/server/unicorn_collector.rb +4 -4
  47. data/lib/prometheus_exporter/server/web_collector.rb +39 -22
  48. data/lib/prometheus_exporter/server/web_server.rb +10 -20
  49. data/lib/prometheus_exporter/version.rb +1 -1
  50. data/prometheus_exporter.gemspec +16 -18
  51. metadata +31 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5381fb78e6440d77a61269f3bf7c40a84b44a53594d687db4a683be3cb82725
4
- data.tar.gz: 18216fbeae6978d5427fa9f97a67bbf3f0ee36e92091a2606b2dadcaa6497d83
3
+ metadata.gz: e8f8c9307f755aa00e95f323d2be11cdf6830f7e420c9bf70d90260e9bc81a85
4
+ data.tar.gz: 216bedbba838f0a84391ef2e85b290aa596cf3c42d27b4cc6bce7a9fae8be01d
5
5
  SHA512:
6
- metadata.gz: 626d1f7c05e5bf21bc499e69fd1ab0d73c94c5a565ac7eae81ec9d43fc93f6cf96b83a6fd72b25846e49371079a9c87a497e719d74c20dfa57c0fb5cbe4507e5
7
- data.tar.gz: b43a57442d6326648cbc3539c50400556575e425756358d45ad39832e099671ca617ea66b6754d16d66693b9fbdf9045b96a95713b36f1f135ab8ab0e38a6d0b
6
+ metadata.gz: 3ad534e47314779c76eb9e80d5de23619cd0865c2337147188d7f2ddba3bff9a6c9cf630e20720899c4e7ef9c95bf1db317a719d08fc241850f902aceae1b5cf
7
+ data.tar.gz: 6e71eab8cf6cdb049612c5afc404d6e399a142ee3eb5bbb3ae897e374ac6474d09f1b6c3ad94ab31f8d12fc52fc9e609a8b066051c89e44ea84be0fa0ec2cf0e
@@ -27,7 +27,7 @@ jobs:
27
27
  strategy:
28
28
  fail-fast: false
29
29
  matrix:
30
- ruby: ['3.1', '3.2', '3.3']
30
+ ruby: ["3.1", "3.2", "3.3"]
31
31
  activerecord: [61, 70, 71]
32
32
 
33
33
  steps:
@@ -42,6 +42,9 @@ jobs:
42
42
  - name: Rubocop
43
43
  run: bundle exec rubocop
44
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
+
45
48
  - name: Run tests
46
49
  run: bundle exec rake
47
50
 
data/.streerc ADDED
@@ -0,0 +1,2 @@
1
+ --print-width=100
2
+ --plugins=plugin/trailing_comma,disable_ternary
data/CHANGELOG CHANGED
@@ -1,3 +1,8 @@
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
+
1
6
  2.1.1 - 2024-06-19
2
7
 
3
8
  - FEATURE: improve good_job instrumentation
data/README.md CHANGED
@@ -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 | 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 |
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
 
data/bench/bench.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../lib/prometheus_exporter'
4
- require_relative '../lib/prometheus_exporter/client'
5
- require_relative '../lib/prometheus_exporter/server'
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 = lambda do
30
- puts "Elapsed for 10k messages is #{Time.now - @start}"
31
- if (@runs -= 1) > 0
32
- @start = Time.now
33
- 10_000.times { @client.send_json(hello: "world") }
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: 12349, collector: collector
39
+ server = PrometheusExporter::Server::WebServer.new port: 12_349, collector: collector
39
40
  server.start
40
- @client = PrometheusExporter::Client.new port: 12349, max_queue_size: 100_000
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") }
@@ -20,8 +20,6 @@ class MyCustomCollector < PrometheusExporter::Server::BaseCollector
20
20
  end
21
21
 
22
22
  def prometheus_metrics_text
23
- @mutex.synchronize do
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
@@ -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
- @socket = nil
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
- @socket = nil
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(database username host port)
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("ActiveRecord connection pool stats not supported in your rails version")
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
- raise "Invalid Config Labels, available options #{ALLOWED_CONFIG_LABELS}" if (config_labels - ALLOWED_CONFIG_LABELS).size > 0
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(pool.spec.config
70
- .select { |k, v| @config_labels.include? k }
71
- .map { |k, v| [k.to_s.dup.prepend("dbconfig_"), v] }.to_h)
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({}) { |l, acc| acc["dbconfig_#{l}"] = pool.db_config.public_send(l) })
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,24 +2,33 @@
2
2
 
3
3
  module PrometheusExporter::Instrumentation
4
4
  class DelayedJob
5
- JOB_CLASS_REGEXP = %r{job_class: ((\w+:{0,2})+)}.freeze
5
+ JOB_CLASS_REGEXP = /job_class: ((\w+:{0,2})+)/.freeze
6
6
 
7
7
  class << self
8
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 = Class.new(Delayed::Plugin) do
13
- callbacks do |lifecycle|
14
- lifecycle.around(:invoke_job) do |job, *args, &block|
15
- max_attempts = Delayed::Worker.max_attempts
16
- enqueued_count = Delayed::Job.where(queue: job.queue).count
17
- pending_count = Delayed::Job.where(attempts: 0, locked_at: nil, queue: job.queue).count
18
- instrumenter.call(job, max_attempts, enqueued_count, pending_count, include_module_name,
19
- *args, &block)
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
20
30
  end
21
31
  end
22
- end
23
32
 
24
33
  Delayed::Worker.plugins << plugin
25
34
  end
@@ -50,7 +59,7 @@ module PrometheusExporter::Instrumentation
50
59
  attempts: attempts,
51
60
  max_attempts: max_attempts,
52
61
  enqueued: enqueued_count,
53
- pending: pending_count
62
+ pending: pending_count,
54
63
  )
55
64
  end
56
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 do
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
@@ -19,7 +19,7 @@ module PrometheusExporter::Instrumentation
19
19
  type: "hutch",
20
20
  name: @klass.class.to_s,
21
21
  success: success,
22
- duration: duration
22
+ duration: duration,
23
23
  )
24
24
  end
25
25
  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; end
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,8 +42,8 @@ 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
- patches = methods.map do |method_name|
46
- <<~RUBY
45
+
46
+ patches = methods.map { |method_name| <<~RUBY }.join("\n")
47
47
  def #{method_name}(...)
48
48
  unless prof = Thread.current[:_method_profiler]
49
49
  return super
@@ -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 patches, __FILE__, patch_source_line
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,14 +70,16 @@ 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
- patches = methods.map do |method_name|
75
- <<~RUBY
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}
77
+
78
78
  def #{method_name}(...)
79
79
  unless prof = Thread.current[:_method_profiler]
80
80
  return #{method_name}__mp_unpatched(...)
81
81
  end
82
+
82
83
  begin
83
84
  start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
84
85
  #{method_name}__mp_unpatched(...)
@@ -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 patches, __FILE__, patch_source_line
95
+ klass.class_eval(patches, __FILE__, patch_source_line)
96
96
  end
97
97
  end
@@ -2,21 +2,14 @@
2
2
 
3
3
  module PrometheusExporter::Instrumentation
4
4
  class PeriodicStats
5
-
6
5
  def self.start(*args, frequency:, client: nil, **kwargs)
7
6
  client ||= PrometheusExporter::Client.default
8
7
 
9
- if !(Numeric === frequency)
10
- raise ArgumentError.new("Expected frequency to be a number")
11
- end
8
+ raise ArgumentError.new("Expected frequency to be a number") if !(Numeric === frequency)
12
9
 
13
- if frequency < 0
14
- raise ArgumentError.new("Expected frequency to be a positive number")
15
- end
10
+ raise ArgumentError.new("Expected frequency to be a positive number") if frequency < 0
16
11
 
17
- if !@worker_loop
18
- raise ArgumentError.new("Worker loop was not set")
19
- end
12
+ raise ArgumentError.new("Worker loop was not set") if !@worker_loop
20
13
 
21
14
  klass = self
22
15
 
@@ -24,18 +17,18 @@ module PrometheusExporter::Instrumentation
24
17
 
25
18
  @stop_thread = false
26
19
 
27
- @thread = Thread.new do
28
- while !@stop_thread
29
- begin
30
- @worker_loop.call
31
- rescue => e
32
- client.logger.error("#{klass} Prometheus Exporter Failed To Collect Stats #{e}")
33
- ensure
34
- sleep frequency
20
+ @thread =
21
+ Thread.new do
22
+ while !@stop_thread
23
+ begin
24
+ @worker_loop.call
25
+ rescue => e
26
+ client.logger.error("#{klass} Prometheus Exporter Failed To Collect Stats #{e}")
27
+ ensure
28
+ sleep frequency
29
+ end
35
30
  end
36
31
  end
37
- end
38
-
39
32
  end
40
33
 
41
34
  def self.started?
@@ -57,6 +50,5 @@ module PrometheusExporter::Instrumentation
57
50
  end
58
51
  @thread = nil
59
52
  end
60
-
61
53
  end
62
54
  end
@@ -3,9 +3,7 @@
3
3
  # collects stats from currently running process
4
4
  module PrometheusExporter::Instrumentation
5
5
  class Process < PeriodicStats
6
-
7
6
  def self.start(client: nil, type: "ruby", frequency: 30, labels: nil)
8
-
9
7
  metric_labels =
10
8
  if labels && type
11
9
  labels.merge(type: type)
@@ -46,14 +44,22 @@ module PrometheusExporter::Instrumentation
46
44
  end
47
45
 
48
46
  def rss
49
- @pagesize ||= `getconf PAGESIZE`.to_i rescue 4096
50
- File.read("/proc/#{pid}/statm").split(' ')[1].to_i * @pagesize rescue 0
47
+ @pagesize ||=
48
+ begin
49
+ `getconf PAGESIZE`.to_i
50
+ rescue StandardError
51
+ 4096
52
+ end
53
+ begin
54
+ File.read("/proc/#{pid}/statm").split(" ")[1].to_i * @pagesize
55
+ rescue StandardError
56
+ 0
57
+ end
51
58
  end
52
59
 
53
60
  def collect_process_stats(metric)
54
61
  metric[:pid] = pid
55
62
  metric[:rss] = rss
56
-
57
63
  end
58
64
 
59
65
  def collect_gc_stats(metric)
@@ -68,7 +74,7 @@ module PrometheusExporter::Instrumentation
68
74
  end
69
75
 
70
76
  def collect_v8_stats(metric)
71
- return if !defined? MiniRacer
77
+ return if !defined?(MiniRacer)
72
78
 
73
79
  metric[:v8_heap_count] = metric[:v8_heap_size] = 0
74
80
  metric[:v8_heap_size] = metric[:v8_physical_size] = 0
@@ -26,7 +26,7 @@ module PrometheusExporter::Instrumentation
26
26
  pid: pid,
27
27
  type: "puma",
28
28
  hostname: ::PrometheusExporter.hostname,
29
- metric_labels: @metric_labels
29
+ metric_labels: @metric_labels,
30
30
  }
31
31
  collect_puma_stats(metric)
32
32
  metric
@@ -7,9 +7,7 @@ module PrometheusExporter::Instrumentation
7
7
  resque_collector = new
8
8
  client ||= PrometheusExporter::Client.default
9
9
 
10
- worker_loop do
11
- client.send_json(resque_collector.collect)
12
- end
10
+ worker_loop { client.send_json(resque_collector.collect) }
13
11
 
14
12
  super
15
13
  end
@@ -2,7 +2,6 @@
2
2
 
3
3
  module PrometheusExporter::Instrumentation
4
4
  class Shoryuken
5
-
6
5
  def initialize(client: nil)
7
6
  @client = client || PrometheusExporter::Client.default
8
7
  end
@@ -19,12 +18,12 @@ module PrometheusExporter::Instrumentation
19
18
  ensure
20
19
  duration = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - start
21
20
  @client.send_json(
22
- type: "shoryuken",
23
- queue: queue,
24
- name: worker.class.name,
25
- success: success,
26
- shutdown: shutdown,
27
- duration: duration
21
+ type: "shoryuken",
22
+ queue: queue,
23
+ name: worker.class.name,
24
+ success: success,
25
+ shutdown: shutdown,
26
+ duration: duration,
28
27
  )
29
28
  end
30
29
  end
@@ -3,8 +3,7 @@
3
3
  require "yaml"
4
4
 
5
5
  module PrometheusExporter::Instrumentation
6
- JOB_WRAPPER_CLASS_NAME =
7
- "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper"
6
+ JOB_WRAPPER_CLASS_NAME = "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper"
8
7
  DELAYED_CLASS_NAMES = %w[
9
8
  Sidekiq::Extensions::DelayedClass
10
9
  Sidekiq::Extensions::DelayedModel
@@ -24,7 +23,7 @@ module PrometheusExporter::Instrumentation
24
23
  type: "sidekiq",
25
24
  name: get_name(job["class"], job),
26
25
  dead: true,
27
- custom_labels: worker_custom_labels
26
+ custom_labels: worker_custom_labels,
28
27
  )
29
28
  end
30
29
  end
@@ -44,8 +43,7 @@ module PrometheusExporter::Instrumentation
44
43
  end
45
44
 
46
45
  def initialize(options = { client: nil })
47
- @client =
48
- options.fetch(:client, nil) || PrometheusExporter::Client.default
46
+ @client = options.fetch(:client, nil) || PrometheusExporter::Client.default
49
47
  end
50
48
 
51
49
  def call(worker, msg, queue)
@@ -67,7 +65,7 @@ module PrometheusExporter::Instrumentation
67
65
  success: success,
68
66
  shutdown: shutdown,
69
67
  duration: duration,
70
- custom_labels: self.class.get_worker_custom_labels(worker.class, msg)
68
+ custom_labels: self.class.get_worker_custom_labels(worker.class, msg),
71
69
  )
72
70
  end
73
71