bc-prometheus-ruby 0.1.5 → 0.2.0

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: f508f25c190541cb70c122a43df4a1080d806c90c9d40bfcd783dfa8ed98f3b0
4
- data.tar.gz: ce143665ff9e84032601aa8a592c22c374f0939a6b3bd708a8fc8b4d38c47eff
3
+ metadata.gz: 6b7632ea975f9fc41399d9a24624eeeadafc08065aff14ab7825713d0aa21757
4
+ data.tar.gz: daf8ffa859833893d9ab6d70ca06605820c77e47b42382317b5ad7ee2aab65bc
5
5
  SHA512:
6
- metadata.gz: 44464c27e557945ff3f1dfbcf130565a1bf88678d252cbfdf882ecdd9753afb35cf20052a16fe15f25e7e396d63fd6d0139f2b13daf550be78864cccb2bbc778
7
- data.tar.gz: c8392da5b98df9d071af54220d5223a99cd3cb0c52c61bb410c2c88db16143c99621eb62810ce7aa5a7c82d96e2c57d28faf02f061b5e1bde700f2f255642b4f
6
+ metadata.gz: 980d28e7517b613fe7296709638c27d4ef69e93533d7ff81701771651d9dbaac11e23dd08eb22a59edea4d804fb21903c888c5f2f46159fddd9c2b4942097fd4
7
+ data.tar.gz: 367ea000ef4cff7ad04da3fe3701eb890f565a2c259b10e624cf48caa62c9d1c91d3d00f3161702f86dacce4cc38ccf3411faf92881e2dcb984afab7d1a3e634
data/CHANGELOG.md CHANGED
@@ -1,47 +1,53 @@
1
1
  Changelog for the bc-prometheus-ruby gem.
2
2
 
3
- h3. Pending Release
3
+ ### Pending Release
4
4
 
5
- h3. 0.1.5
5
+ ### 0.2.0
6
+
7
+ - Add the ability to pass custom collectors and type collectors to the web instrumenter
8
+ - Add base collector and type collector classes for ease of development of custom integrations
9
+ - Change railtie to after initialization to allow for customization
10
+
11
+ ### 0.1.5
6
12
 
7
13
  - Fix issue where puma collector was not being registered on the server
8
14
 
9
- h3. 0.1.4
15
+ ### 0.1.4
10
16
 
11
17
  - Handle circumstances when before_fork_callbacks is called outside of the web process
12
18
 
13
- h3. 0.1.3
19
+ ### 0.1.3
14
20
 
15
21
  - Move to bigcommerce fork of multitrap to handle IGNORE clauses more cleanly
16
22
 
17
- h3. 0.1.1
23
+ ### 0.1.1
18
24
 
19
25
  - Add multitrap to more cleanly handle trap signals
20
26
  - Use proc in signal handlers for consistent trap handling
21
27
 
22
- h3. 0.1.0
28
+ ### 0.1.0
23
29
 
24
30
  - Replace WEBrick server from PrometheusExporter with Thin server implementation to reduce memory leakage
25
31
  - Utilize NET::HTTP instead of direct sockets to prevent bad socket errors
26
32
 
27
- h3. 0.0.5
33
+ ### 0.0.5
28
34
 
29
35
  - Add resque instrumentation
30
36
 
31
- h3. 0.0.4
37
+ ### 0.0.4
32
38
 
33
39
  - Properly handle SIGINT/SIGTERM to shutdown prometheus exporter
34
40
  - Add process names to log output for easier debugging
35
41
 
36
- h3. 0.0.3
42
+ ### 0.0.3
37
43
 
38
44
  - Add hutch instrumentor for hutch / rmq support
39
45
 
40
- h3. 0.0.2
46
+ ### 0.0.2
41
47
 
42
48
  - Better support for older Rails / Puma versions
43
49
  - Adds basic support for non-Rails applications
44
50
 
45
- h3. 0.0.1
51
+ ### 0.0.1
46
52
 
47
53
  - Initial public release
@@ -30,7 +30,9 @@ require_relative 'prometheus/configuration'
30
30
  require_relative 'prometheus/server'
31
31
  require_relative 'prometheus/client'
32
32
 
33
+ require_relative 'prometheus/collectors/base'
33
34
  require_relative 'prometheus/collectors/resque'
35
+ require_relative 'prometheus/type_collectors/base'
34
36
  require_relative 'prometheus/type_collectors/resque'
35
37
 
36
38
  require_relative 'prometheus/instrumentors/web'
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2019-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ module Bigcommerce
19
+ module Prometheus
20
+ module Collectors
21
+ ##
22
+ # Base class for collectors
23
+ #
24
+ class Base
25
+ ##
26
+ # Start the collector
27
+ #
28
+ def self.start(*args, &block)
29
+ process_collector = new(*args, &block)
30
+
31
+ stop if @thread
32
+
33
+ @thread = Thread.new do
34
+ Kernel.loop do
35
+ process_collector.run
36
+ end
37
+ end
38
+ end
39
+
40
+ ##
41
+ # Stop the collector
42
+ #
43
+ def self.stop
44
+ t = @thread
45
+ return unless t
46
+
47
+ t.kill
48
+ @thread = nil
49
+ end
50
+
51
+ ##
52
+ # @param [PrometheusExporter::Client] client
53
+ # @param [String] type
54
+ # @param [Integer] frequency
55
+ # @param [Hash] options
56
+ #
57
+ def initialize(client: nil, type: nil, frequency: nil, options: nil)
58
+ @client = client || PrometheusExporter::Client.default
59
+ @type = type || self.class.to_s.downcase.gsub('::', '_').gsub('collector', '')
60
+ @frequency = frequency || 15
61
+ @options = options || {}
62
+ @logger = Bigcommerce::Prometheus.logger
63
+ end
64
+
65
+ ##
66
+ # Run the collector and send stats
67
+ #
68
+ def run
69
+ metrics = { type: @type }
70
+ metrics = collect(metrics)
71
+ @logger.debug "[bigcommerce-prometheus] Pushing #{@type} metrics to type collector: #{metrics.inspect}"
72
+ @client.send_json(metrics)
73
+ rescue StandardError => e
74
+ @logger.error("Prometheus Exporter Failed To Collect #{@type} Stats #{e}")
75
+ ensure
76
+ sleep @frequency
77
+ end
78
+
79
+ ##
80
+ # Collect metrics. This should be overridden in derivative collectors
81
+ #
82
+ # @param [Hash] metrics
83
+ # @return [Hash]
84
+ #
85
+ def collect(metrics = {})
86
+ metrics
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -22,54 +22,21 @@ module Bigcommerce
22
22
  # Collect metrics to push to the server type collector
23
23
  #
24
24
  class Resque
25
- include Bigcommerce::Prometheus::Loggable
26
-
27
- ##
28
- # @param [Bigcommerce::Prometheus::Client] client
29
- # @param [Integer] frequency
30
- #
31
- def initialize(client:, frequency: nil)
32
- @client = client || Bigcommerce::Prometheus.client
33
- @frequency = frequency || 15
34
- end
35
-
36
25
  ##
37
- # Start the collector
26
+ # @param [Hash] metrics
27
+ # @return [Hash]
38
28
  #
39
- def self.start(client: nil, frequency: nil)
40
- collector = new(client: client, frequency: frequency)
41
- Thread.new do
42
- loop do
43
- collector.run
44
- end
45
- end
46
- end
47
-
48
- def run
49
- metric = collect
50
- logger.debug "[bigcommerce-prometheus] Pushing resque metrics to type collector: #{metric.inspect}"
51
- @client.send_json metric
52
- rescue StandardError => e
53
- logger.error "[bigcommerce-prometheus] Failed to collect resque prometheus stats: #{e.message}"
54
- ensure
55
- sleep @frequency
56
- end
57
-
58
- private
59
-
60
- def collect
29
+ def collect(metrics = {})
61
30
  info = ::Resque.info
62
31
 
63
- metric = {}
64
- metric[:type] = 'resque'
65
- metric[:environment] = info[:environment].to_s
66
- metric[:workers_total] = info[:workers].to_i
67
- metric[:jobs_failed_total] = info[:failed].to_i
68
- metric[:jobs_pending_total] = info[:pending].to_i
69
- metric[:jobs_processed_total] = info[:processed].to_i
70
- metric[:queues_total] = info[:queues].to_i
71
- metric[:queues] = queue_sizes
72
- metric
32
+ metrics[:environment] = info[:environment].to_s
33
+ metrics[:workers_total] = info[:workers].to_i
34
+ metrics[:jobs_failed_total] = info[:failed].to_i
35
+ metrics[:jobs_pending_total] = info[:pending].to_i
36
+ metrics[:jobs_processed_total] = info[:processed].to_i
37
+ metrics[:queues_total] = info[:queues].to_i
38
+ metrics[:queues] = queue_sizes
39
+ metrics
73
40
  end
74
41
 
75
42
  def queue_sizes
@@ -34,7 +34,9 @@ module Bigcommerce
34
34
  server_host: '0.0.0.0',
35
35
  server_port: PrometheusExporter::DEFAULT_PORT,
36
36
  server_timeout: PrometheusExporter::DEFAULT_TIMEOUT,
37
- server_prefix: PrometheusExporter::DEFAULT_PREFIX
37
+ server_prefix: PrometheusExporter::DEFAULT_PREFIX,
38
+ web_collectors: [],
39
+ web_type_collectors: []
38
40
  }.freeze
39
41
 
40
42
  attr_accessor *VALID_CONFIG_KEYS.keys
@@ -89,6 +91,7 @@ module Bigcommerce
89
91
 
90
92
  self.puma_process_label = ENV.fetch('PROMETHEUS_PUMA_PROCESS_LABEL', 'web').to_s
91
93
  self.puma_collection_frequency = ENV.fetch('PROMETHEUS_PUMA_COLLECTION_FREQUENCY', 30).to_i
94
+ self.web_type_collectors = []
92
95
  end
93
96
 
94
97
  ##
@@ -31,6 +31,8 @@ module Bigcommerce
31
31
  @server_timeout = Bigcommerce::Prometheus.server_timeout
32
32
  @server_prefix = Bigcommerce::Prometheus.server_prefix
33
33
  @process_name = Bigcommerce::Prometheus.process_name
34
+ @collectors = Bigcommerce::Prometheus.web_collectors || []
35
+ @type_collectors = Bigcommerce::Prometheus.web_type_collectors || []
34
36
  end
35
37
 
36
38
  ##
@@ -65,6 +67,9 @@ module Bigcommerce
65
67
  server.add_type_collector(PrometheusExporter::Server::ActiveRecordCollector.new)
66
68
  server.add_type_collector(PrometheusExporter::Server::WebCollector.new)
67
69
  server.add_type_collector(PrometheusExporter::Server::PumaCollector.new)
70
+ @type_collectors.each do |tc|
71
+ server.add_type_collector(tc)
72
+ end
68
73
  server.start
69
74
  end
70
75
  end
@@ -73,6 +78,7 @@ module Bigcommerce
73
78
  @app.config.after_fork_callbacks = [] unless @app.config.after_fork_callbacks
74
79
  @app.config.after_fork_callbacks << lambda do
75
80
  ::Bigcommerce::Prometheus::Integrations::Puma.start
81
+ @collectors.each(&:start)
76
82
  end
77
83
  end
78
84
 
@@ -22,7 +22,7 @@ module Bigcommerce
22
22
  # Railtie for automatic configuration of Rails environments
23
23
  #
24
24
  class Railtie < ::Rails::Railtie
25
- initializer 'zzz_bigcommerce.prometheus.configure_rails_initialization' do |app|
25
+ config.after_initialize do |app|
26
26
  Bigcommerce::Prometheus::Instrumentors::Web.new(app: app).start
27
27
  end
28
28
  end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2019-present, BigCommerce Pty. Ltd. All rights reserved
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ # documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ # persons to whom the Software is furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
11
+ # Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+ #
18
+ module Bigcommerce
19
+ module Prometheus
20
+ module TypeCollectors
21
+ ##
22
+ # Base type collector class
23
+ #
24
+ class Base < PrometheusExporter::Server::TypeCollector
25
+ attr_reader :type
26
+
27
+ ##
28
+ # @param [String] type
29
+ # @param [Hash] default_labels
30
+ #
31
+ def initialize(type: nil, default_labels: {})
32
+ @type = type || self.class.to_s.downcase.gsub('::', '_').gsub('typecollector', '')
33
+ @default_labels = default_labels || {}
34
+ @metrics = build_metrics
35
+ end
36
+
37
+ ##
38
+ # @return [Array]
39
+ #
40
+ def metrics
41
+ return [] unless @metrics.any?
42
+
43
+ @metrics.values
44
+ end
45
+
46
+ ##
47
+ # @param [Symbol] key
48
+ #
49
+ def metric(key)
50
+ @metrics.fetch(key.to_sym, nil)
51
+ end
52
+
53
+ ##
54
+ # Collect metrics from input data
55
+ #
56
+ # @param [Hash] data
57
+ #
58
+ def collect(data)
59
+ custom_labels = data.fetch('custom_labels', nil)
60
+ labels = custom_labels.nil? ? @default_labels : @default_labels.merge(custom_labels)
61
+ collect_metrics(data: data, labels: labels)
62
+ end
63
+
64
+ private
65
+
66
+ ##
67
+ # Collect metrics. Implementations of translating metrics to observed calls should happen here.
68
+ #
69
+ def collect_metrics(*)
70
+ raise NotImplementedError, 'Must implement collect_metrics'
71
+ end
72
+
73
+ ##
74
+ # Build and return all observable metrics. This should be a hash of symbol keys that map to
75
+ # PrometheusExporter::Metric::Base objects.
76
+ #
77
+ # @return [Hash]
78
+ #
79
+ def build_metrics
80
+ {}
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -21,59 +21,33 @@ module Bigcommerce
21
21
  ##
22
22
  # Collect resque data from collectors and parse them into metrics
23
23
  #
24
- class Resque < PrometheusExporter::Server::TypeCollector
24
+ class Resque < Bigcommerce::Prometheus::TypeCollectors::Base
25
25
  ##
26
26
  # Initialize the collector
27
27
  #
28
- def initialize
29
- @workers_total = PrometheusExporter::Metric::Gauge.new('resque_workers_total', 'Number of active workers')
30
- @jobs_failed_total = PrometheusExporter::Metric::Gauge.new('jobs_failed_total', 'Number of failed jobs')
31
- @jobs_pending_total = PrometheusExporter::Metric::Gauge.new('jobs_pending_total', 'Number of pending jobs')
32
- @jobs_processed_total = PrometheusExporter::Metric::Gauge.new('jobs_processed_total', 'Number of processed jobs')
33
- @queues_total = PrometheusExporter::Metric::Gauge.new('queues_total', 'Number of total queues')
34
- @queue_sizes = PrometheusExporter::Metric::Gauge.new('queue_sizes', 'Size of each queue')
35
- end
36
-
37
- ##
38
- # @return [String]
39
- #
40
- def type
41
- 'resque'
42
- end
43
-
44
- ##
45
- # @return [Array]
46
- #
47
- def metrics
48
- return [] unless @workers_total
49
-
50
- [
51
- @workers_total,
52
- @jobs_failed_total,
53
- @jobs_pending_total,
54
- @jobs_processed_total,
55
- @queues_total,
56
- @queue_sizes
57
- ]
28
+ def build_metrics
29
+ {
30
+ workers_total: PrometheusExporter::Metric::Gauge.new('resque_workers_total', 'Number of active workers'),
31
+ jobs_failed_total: PrometheusExporter::Metric::Gauge.new('jobs_failed_total', 'Number of failed jobs'),
32
+ jobs_pending_total: PrometheusExporter::Metric::Gauge.new('jobs_pending_total', 'Number of pending jobs'),
33
+ jobs_processed_total: PrometheusExporter::Metric::Gauge.new('jobs_processed_total', 'Number of processed jobs'),
34
+ queues_total: PrometheusExporter::Metric::Gauge.new('queues_total', 'Number of total queues'),
35
+ queue_sizes: PrometheusExporter::Metric::Gauge.new('queue_sizes', 'Size of each queue')
36
+ }
58
37
  end
59
38
 
60
39
  ##
61
40
  # Collect resque metrics from input data
62
41
  #
63
- def collect(obj)
64
- default_labels = { environment: obj['environment'] }
65
-
66
- custom_labels = obj['custom_labels']
67
- labels = custom_labels.nil? ? default_labels : default_labels.merge(custom_labels)
68
-
69
- @workers_total.observe(obj['workers_total'], labels)
70
- @jobs_failed_total.observe(obj['jobs_failed_total'], labels)
71
- @jobs_pending_total.observe(obj['jobs_pending_total'], labels)
72
- @jobs_processed_total.observe(obj['jobs_processed_total'], labels)
73
- @queues_total.observe(obj['queues_total'], labels)
74
-
75
- obj['queues'].each do |name, size|
76
- @queue_sizes.observe(size, labels.merge(queue: name))
42
+ def collect_metrics(data:, labels: {})
43
+ metric(:workers_total).observe(obj['workers_total'], labels)
44
+ metric(:jobs_failed_total).observe(obj['jobs_failed_total'], labels)
45
+ metric(:jobs_pending_total).observe(obj['jobs_pending_total'], labels)
46
+ metric(:jobs_processed_total).observe(obj['jobs_processed_total'], labels)
47
+ metric(:queues_total).observe(obj['queues_total'], labels)
48
+
49
+ data['queues'].each do |name, size|
50
+ metric(:queue_sizes).observe(size, labels.merge(queue: name))
77
51
  end
78
52
  end
79
53
  end
@@ -17,6 +17,6 @@
17
17
  #
18
18
  module Bigcommerce
19
19
  module Prometheus
20
- VERSION = '0.1.5'
20
+ VERSION = '0.2.0'
21
21
  end
22
22
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bc-prometheus-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shaun McCormick
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-12 00:00:00.000000000 Z
11
+ date: 2019-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -177,6 +177,7 @@ files:
177
177
  - bc-prometheus-ruby.gemspec
178
178
  - lib/bigcommerce/prometheus.rb
179
179
  - lib/bigcommerce/prometheus/client.rb
180
+ - lib/bigcommerce/prometheus/collectors/base.rb
180
181
  - lib/bigcommerce/prometheus/collectors/resque.rb
181
182
  - lib/bigcommerce/prometheus/configuration.rb
182
183
  - lib/bigcommerce/prometheus/instrumentors/hutch.rb
@@ -195,6 +196,7 @@ files:
195
196
  - lib/bigcommerce/prometheus/servers/thin/rack_app.rb
196
197
  - lib/bigcommerce/prometheus/servers/thin/server.rb
197
198
  - lib/bigcommerce/prometheus/servers/thin/server_metrics.rb
199
+ - lib/bigcommerce/prometheus/type_collectors/base.rb
198
200
  - lib/bigcommerce/prometheus/type_collectors/resque.rb
199
201
  - lib/bigcommerce/prometheus/version.rb
200
202
  homepage: https://github.com/bigcommerce/bc-prometheus-ruby