prometheus_exporter 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f5e708b8c63be6ecff9750deebf18cad149d9b4fa7350a4523af2f145caffec5
4
- data.tar.gz: 1204a53af367dc60e24ded2e1630e2b447ef79d3caff32165ac5c40b62955ded
3
+ metadata.gz: 0a8fb6585d155b56625dcd0d89c41301659e5b32cfc8272a340c7b067dbf686a
4
+ data.tar.gz: 6e5715300786de15f2906b4f8a5603bd19150cb1c511cb83e5c3a3bdf53a5f5b
5
5
  SHA512:
6
- metadata.gz: 5dee50712e73be92702e2948a0a69aa8b8007df59de35f10c5980d9d5a2653092a4247e7ad207713460df80f59bb0691835a3aa2b04fa751d28cc5b9c3f66f48
7
- data.tar.gz: 0af7415fd207b1eb5f7f62639f8d48bc7735df9397537524c536631d24150b9b7daa87d17652f070a79f8134d50e780c9143ddeedcfc2d44eaa27586ffe64b19
6
+ metadata.gz: 52cce25c1403f889f65fc25b054ec22703f32dad1c32d14e35af74b65308c2bf7f0a10e8343bd906c98f884167243484f43114700c3175113e8e75f002421823
7
+ data.tar.gz: de8bc77ce936ad4f045c0f34907febb881518b537d5828bfeba5476924355157902f6618a0acc37aa1202ff604853f7bb3908ba78478a6cd3cf57bb1b0f5ff66
data/CHANGELOG CHANGED
@@ -1,6 +1,10 @@
1
+ 2.0.1 - 2022-02-24
2
+
3
+ - FIX: ensure threads do not leak when calling #start repeatedly on instrumentation classes, this is an urgent patch for Puma integration
4
+
1
5
  2.0.0 - 2022-02-18
2
6
 
3
- - FEATURE: Add per worker custom labels
7
+ - FEATURE: Add per worker custom labels
4
8
  - FEATURE: support custom histogram buckets
5
9
  - FIX: all metrics are exposing status label, and not only `http_requests_total`
6
10
  - BREAKING: rename all `http_duration` metrics to `http_request_duration` to match prometheus official naming conventions (See https://prometheus.io/docs/practices/naming/#metric-names).
data/README.md CHANGED
@@ -575,7 +575,10 @@ The easiest way to gather this metrics is to put the following in your `puma.rb`
575
575
  # puma.rb config
576
576
  after_worker_boot do
577
577
  require 'prometheus_exporter/instrumentation'
578
- PrometheusExporter::Instrumentation::Puma.start
578
+ # optional check, avoids spinning up and down threads per worker
579
+ if !PrometheusExporter::Instrumentation::Puma.started?
580
+ PrometheusExporter::Instrumentation::Puma.start
581
+ end
579
582
  end
580
583
  ```
581
584
 
@@ -2,11 +2,10 @@
2
2
 
3
3
  # collects stats from currently running process
4
4
  module PrometheusExporter::Instrumentation
5
- class ActiveRecord
5
+ class ActiveRecord < PeriodicStats
6
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
-
10
9
  client ||= PrometheusExporter::Client.default
11
10
 
12
11
  # Not all rails versions support connection pool stats
@@ -20,20 +19,12 @@ module PrometheusExporter::Instrumentation
20
19
 
21
20
  active_record_collector = new(custom_labels, config_labels)
22
21
 
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
- client.logger.error("Prometheus Exporter Failed To Collect Process Stats #{e}")
32
- ensure
33
- sleep frequency
34
- end
35
- end
22
+ worker_loop do
23
+ metrics = active_record_collector.collect
24
+ metrics.each { |metric| client.send_json metric }
36
25
  end
26
+
27
+ super
37
28
  end
38
29
 
39
30
  def self.validate_config_labels(config_labels)
@@ -41,13 +32,6 @@ module PrometheusExporter::Instrumentation
41
32
  raise "Invalid Config Labels, available options #{ALLOWED_CONFIG_LABELS}" if (config_labels - ALLOWED_CONFIG_LABELS).size > 0
42
33
  end
43
34
 
44
- def self.stop
45
- if t = @thread
46
- t.kill
47
- @thread = nil
48
- end
49
- end
50
-
51
35
  def initialize(metric_labels, config_labels)
52
36
  @metric_labels = metric_labels
53
37
  @config_labels = config_labels
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PrometheusExporter::Instrumentation
4
+ class PeriodicStats
5
+
6
+ def self.start(*args, frequency:, client: nil, **kwargs)
7
+ client ||= PrometheusExporter::Client.default
8
+
9
+ if !(Numeric === frequency)
10
+ raise ArgumentError.new("Expected frequency to be a number")
11
+ end
12
+
13
+ if frequency < 0
14
+ raise ArgumentError.new("Expected frequency to be a positive number")
15
+ end
16
+
17
+ if !@worker_loop
18
+ raise ArgumentError.new("Worker loop was not set")
19
+ end
20
+
21
+ klass = self
22
+
23
+ stop
24
+
25
+ @stop_thread = false
26
+
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
35
+ end
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ def self.started?
42
+ !!@thread&.alive?
43
+ end
44
+
45
+ def self.worker_loop(&blk)
46
+ @worker_loop = blk
47
+ end
48
+
49
+ def self.stop
50
+ # to avoid a warning
51
+ @thread = nil if !defined?(@thread)
52
+
53
+ if @thread&.alive?
54
+ @stop_thread = true
55
+ @thread.wakeup
56
+ @thread.join
57
+ end
58
+ @thread = nil
59
+ end
60
+
61
+ end
62
+ end
@@ -2,8 +2,7 @@
2
2
 
3
3
  # collects stats from currently running process
4
4
  module PrometheusExporter::Instrumentation
5
- class Process
6
- @thread = nil if !defined?(@thread)
5
+ class Process < PeriodicStats
7
6
 
8
7
  def self.start(client: nil, type: "ruby", frequency: 30, labels: nil)
9
8
 
@@ -19,27 +18,12 @@ module PrometheusExporter::Instrumentation
19
18
  process_collector = new(metric_labels)
20
19
  client ||= PrometheusExporter::Client.default
21
20
 
22
- stop if @thread
23
-
24
- @thread = Thread.new do
25
- while true
26
- begin
27
- metric = process_collector.collect
28
- client.send_json metric
29
- rescue => e
30
- client.logger.error("Prometheus Exporter Failed To Collect Process Stats #{e}")
31
- ensure
32
- sleep frequency
33
- end
34
- end
21
+ worker_loop do
22
+ metric = process_collector.collect
23
+ client.send_json metric
35
24
  end
36
- end
37
25
 
38
- def self.stop
39
- if t = @thread
40
- t.kill
41
- @thread = nil
42
- end
26
+ super
43
27
  end
44
28
 
45
29
  def initialize(metric_labels)
@@ -4,22 +4,17 @@ require "json"
4
4
 
5
5
  # collects stats from puma
6
6
  module PrometheusExporter::Instrumentation
7
- class Puma
7
+ class Puma < PeriodicStats
8
8
  def self.start(client: nil, frequency: 30, labels: {})
9
9
  puma_collector = new(labels)
10
10
  client ||= PrometheusExporter::Client.default
11
- Thread.new do
12
- while true
13
- begin
14
- metric = puma_collector.collect
15
- client.send_json metric
16
- rescue => e
17
- client.logger.error("Prometheus Exporter Failed To Collect Puma Stats #{e}")
18
- ensure
19
- sleep frequency
20
- end
21
- end
11
+
12
+ worker_loop do
13
+ metric = puma_collector.collect
14
+ client.send_json metric
22
15
  end
16
+
17
+ super
23
18
  end
24
19
 
25
20
  def initialize(metric_labels = {})
@@ -2,21 +2,16 @@
2
2
 
3
3
  # collects stats from resque
4
4
  module PrometheusExporter::Instrumentation
5
- class Resque
5
+ class Resque < PeriodicStats
6
6
  def self.start(client: nil, frequency: 30)
7
7
  resque_collector = new
8
8
  client ||= PrometheusExporter::Client.default
9
- Thread.new do
10
- while true
11
- begin
12
- client.send_json(resque_collector.collect)
13
- rescue => e
14
- client.logger.error("Prometheus Exporter Failed To Collect Resque Stats #{e}")
15
- ensure
16
- sleep frequency
17
- end
18
- end
9
+
10
+ worker_loop do
11
+ client.send_json(resque_collector.collect)
19
12
  end
13
+
14
+ super
20
15
  end
21
16
 
22
17
  def collect
@@ -1,22 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PrometheusExporter::Instrumentation
4
- class SidekiqProcess
4
+ class SidekiqProcess < PeriodicStats
5
5
  def self.start(client: nil, frequency: 30)
6
6
  client ||= PrometheusExporter::Client.default
7
7
  sidekiq_process_collector = new
8
8
 
9
- Thread.new do
10
- loop do
11
- begin
12
- client.send_json(sidekiq_process_collector.collect)
13
- rescue StandardError => e
14
- STDERR.puts("Prometheus Exporter Failed To Collect Sidekiq Processes metrics #{e}")
15
- ensure
16
- sleep frequency
17
- end
18
- end
9
+ worker_loop do
10
+ client.send_json(sidekiq_process_collector.collect)
19
11
  end
12
+
13
+ super
20
14
  end
21
15
 
22
16
  def initialize
@@ -1,22 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PrometheusExporter::Instrumentation
4
- class SidekiqQueue
4
+ class SidekiqQueue < PeriodicStats
5
5
  def self.start(client: nil, frequency: 30, all_queues: false)
6
6
  client ||= PrometheusExporter::Client.default
7
7
  sidekiq_queue_collector = new(all_queues: all_queues)
8
8
 
9
- Thread.new do
10
- loop do
11
- begin
12
- client.send_json(sidekiq_queue_collector.collect)
13
- rescue StandardError => e
14
- client.logger.error("Prometheus Exporter Failed To Collect Sidekiq Queue metrics #{e}")
15
- ensure
16
- sleep frequency
17
- end
18
- end
9
+ worker_loop do
10
+ client.send_json(sidekiq_queue_collector.collect)
19
11
  end
12
+
13
+ super
20
14
  end
21
15
 
22
16
  def initialize(all_queues: false)
@@ -1,22 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PrometheusExporter::Instrumentation
4
- class SidekiqStats
4
+ class SidekiqStats < PeriodicStats
5
5
  def self.start(client: nil, frequency: 30)
6
6
  client ||= PrometheusExporter::Client.default
7
7
  sidekiq_stats_collector = new
8
8
 
9
- Thread.new do
10
- loop do
11
- begin
12
- client.send_json(sidekiq_stats_collector.collect)
13
- rescue StandardError => e
14
- STDERR.puts("Prometheus Exporter Failed To Collect Sidekiq Stats metrics #{e}")
15
- ensure
16
- sleep frequency
17
- end
18
- end
9
+ worker_loop do
10
+ client.send_json(sidekiq_stats_collector.collect)
19
11
  end
12
+
13
+ super
20
14
  end
21
15
 
22
16
  def collect
@@ -8,22 +8,17 @@ end
8
8
 
9
9
  module PrometheusExporter::Instrumentation
10
10
  # collects stats from unicorn
11
- class Unicorn
11
+ class Unicorn < PeriodicStats
12
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
- Thread.new do
16
- loop do
17
- begin
18
- metric = unicorn_collector.collect
19
- client.send_json metric
20
- rescue StandardError => e
21
- client.logger.error("Prometheus Exporter Failed To Collect Unicorn Stats #{e}")
22
- ensure
23
- sleep frequency
24
- end
25
- end
15
+
16
+ worker_loop do
17
+ metric = unicorn_collector.collect
18
+ client.send_json metric
26
19
  end
20
+
21
+ super
27
22
  end
28
23
 
29
24
  def initialize(pid_file:, listener_address:)
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "client"
4
+ require_relative "instrumentation/periodic_stats"
4
5
  require_relative "instrumentation/process"
5
6
  require_relative "instrumentation/method_profiler"
6
7
  require_relative "instrumentation/sidekiq"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PrometheusExporter
4
- VERSION = '2.0.0'
4
+ VERSION = '2.0.1'
5
5
  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: 2.0.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Saffron
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-18 00:00:00.000000000 Z
11
+ date: 2022-02-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: webrick
@@ -238,6 +238,7 @@ files:
238
238
  - lib/prometheus_exporter/instrumentation/delayed_job.rb
239
239
  - lib/prometheus_exporter/instrumentation/hutch.rb
240
240
  - lib/prometheus_exporter/instrumentation/method_profiler.rb
241
+ - lib/prometheus_exporter/instrumentation/periodic_stats.rb
241
242
  - lib/prometheus_exporter/instrumentation/process.rb
242
243
  - lib/prometheus_exporter/instrumentation/puma.rb
243
244
  - lib/prometheus_exporter/instrumentation/resque.rb