prometheus_exporter 2.1.1 → 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.
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