bc-prometheus-ruby 0.6.0 → 0.8.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a698cc0ac06efacbba9d2448adf0cac2c1f1f54468ee3ba4c14fab8e5c25e012
4
- data.tar.gz: f8c629aa6c16174692bf804271af7edbf1f087d9abb7bc2ff32400a01d00a001
3
+ metadata.gz: a7a2ca2f975be9d346e217c4a13e4ca702a573889383c43292094f66aa82c562
4
+ data.tar.gz: 2724f8826c1ee9d668357676834f15dc24836ed1d05337f7b217133119fb4e26
5
5
  SHA512:
6
- metadata.gz: e7b37136f17cc98bd2f8c88adc4668f4685965602453261a27ff90516788c86d6571ceb15158e7fd0a3fb78f42e31c6cafbd4beacf4b590f6e82395682c33174
7
- data.tar.gz: 5879abda273f9d1b127483f7ee0f6083bc013fe4376033e15f917a62113d1727b4d32e34381e98dbbab90981fd7e7e124242775cd3c18e6e792b4a451ecd7aa2
6
+ metadata.gz: c1e174d621f686a1d32b4db922d4409f1cdffa1f0afd2c6f6b853f51978150b53be7ae3237fc0a1b8daf139423c98f0186ad317345b16a070eb0824f00249ef3
7
+ data.tar.gz: 8c215d4cb4349041e082bedaee24580afbc4f567bf6e8af848c0e00afa42b228a982790f6d21acfdbf6023de82aaa9cfecc2e55b625730e75102443c1e946ef1
data/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@ Changelog for the bc-prometheus-ruby gem.
2
2
 
3
3
  ### Pending Release
4
4
 
5
+ ## 0.8.0
6
+
7
+ - Add support for Ruby 3.4
8
+ - Drop support for Ruby 3.0, 3.1
9
+
10
+ ## 0.7.0
11
+
12
+ - Add CI suite for Ruby 3.3
13
+ - Update README for starting prometheus with Puma
14
+ - Add logging with prometheus server starts
15
+ - Migrate from thin to puma as the web server
16
+
5
17
  ## 0.6.0
6
18
 
7
19
  - Add support for Ruby 3.1/3.2
@@ -40,13 +52,13 @@ Changelog for the bc-prometheus-ruby gem.
40
52
  - Add ability to pass custom resque and hutch Collectors/TypeCollectors
41
53
  - Add ENV support for all configuration elements
42
54
  - Fix issue where base collector did not use Bigcommerce::Prometheus.client
43
- - Expose new `push` method for Collectors::Base to ease use of custom ad hoc metrics
55
+ - Expose new `push` method for Collectors::Base to ease use of custom ad hoc metrics
44
56
 
45
57
  ### 0.2.4
46
58
 
47
- - Fix cant modify frozen array error when using bc-prometheus-ruby outside a web process
59
+ - Fix cant modify frozen array error when using bc-prometheus-ruby outside a web process
48
60
  but within rails
49
-
61
+
50
62
  ### 0.2.3
51
63
 
52
64
  - Set default STDOUT logger to INFO level
@@ -55,7 +67,7 @@ Changelog for the bc-prometheus-ruby gem.
55
67
  ### 0.2.2
56
68
 
57
69
  - Fix missing inheritance for resque collector
58
-
70
+
59
71
  ### 0.2.1
60
72
 
61
73
  - Prevent starting of Puma integration if Puma is not loaded
data/README.md CHANGED
@@ -14,6 +14,14 @@ Then in your `application.rb`, prior to extending `Rails::Application` or any in
14
14
  require 'bigcommerce/prometheus'
15
15
  ```
16
16
 
17
+ Then in your web server config file (e.g. `puma.rb`)
18
+
19
+ ```ruby
20
+ before_fork do
21
+ Rails.application.config.before_fork_callbacks.each(&:call)
22
+ end
23
+ ```
24
+
17
25
  You can then view your metrics at: http://0.0.0.0:9394/metrics
18
26
 
19
27
  ## Puma
@@ -31,17 +31,13 @@ Gem::Specification.new do |spec|
31
31
 
32
32
  spec.files = Dir['README.md', 'CHANGELOG.md', 'CODE_OF_CONDUCT.md', 'lib/**/*', 'bc-prometheus-ruby.gemspec']
33
33
  spec.require_paths = ['lib']
34
- spec.required_ruby_version = '>= 3.0'
35
-
36
- spec.add_development_dependency 'bundler-audit', '>= 0.6'
37
- spec.add_development_dependency 'pry', '>= 0.12'
38
- spec.add_development_dependency 'rake', '>= 10.0'
39
- spec.add_development_dependency 'rspec', '>= 3.8'
40
- spec.add_development_dependency 'rspec_junit_formatter', '>= 0.4'
41
- spec.add_development_dependency 'rubocop', '>= 1.0'
42
- spec.add_development_dependency 'simplecov', '>= 0.16'
34
+ spec.required_ruby_version = '>= 3.2'
43
35
 
44
36
  spec.add_runtime_dependency 'bigcommerce-multitrap', '~> 0.1'
45
37
  spec.add_runtime_dependency 'prometheus_exporter', '~> 0.7'
46
- spec.add_runtime_dependency 'thin', '~> 1.7'
38
+ spec.add_runtime_dependency 'puma', '> 5'
39
+ spec.add_runtime_dependency 'rack', '>= 3.0'
40
+ spec.add_runtime_dependency 'rake', '>= 10.0'
41
+
42
+ spec.add_development_dependency 'activesupport', '>= 6.0'
47
43
  end
@@ -69,6 +69,14 @@ module Bigcommerce
69
69
  URI("http://#{@host}:#{@port}#{path}")
70
70
  end
71
71
 
72
+ ##
73
+ # @param [String] str
74
+ def send(str)
75
+ return unless Bigcommerce::Prometheus.enabled
76
+
77
+ super
78
+ end
79
+
72
80
  ##
73
81
  # Process the current queue and flush to the collector
74
82
  #
@@ -54,7 +54,8 @@ module Bigcommerce
54
54
  web_type_collectors: [],
55
55
 
56
56
  # Additional configuration
57
- railtie_disabled: ENV.fetch('PROMETHEUS_DISABLE_RAILTIE', 0).to_i.positive?
57
+ railtie_disabled: ENV.fetch('PROMETHEUS_DISABLE_RAILTIE', 0).to_i.positive?,
58
+ active_record_enabled: ENV.fetch('PROMETHEUS_ACTIVE_RECORD_ENABLED', 1).to_i.positive?
58
59
  }.freeze
59
60
 
60
61
  attr_accessor *VALID_CONFIG_KEYS.keys
@@ -46,10 +46,12 @@ module Bigcommerce
46
46
 
47
47
  server.add_type_collector(PrometheusExporter::Server::ActiveRecordCollector.new)
48
48
  server.add_type_collector(PrometheusExporter::Server::HutchCollector.new)
49
+ ::Bigcommerce::Prometheus::Integrations::ActiveRecordSql.register_type_collector(server, process_name: @process_name)
49
50
  @type_collectors.each do |tc|
50
51
  server.add_type_collector(tc)
51
52
  end
52
53
  server.start
54
+ ::Bigcommerce::Prometheus::Integrations::ActiveRecordSql.start_safe(client: Bigcommerce::Prometheus.client, process_name: @process_name)
53
55
  setup_middleware
54
56
  rescue StandardError => e
55
57
  logger.error "[bigcommerce-prometheus][#{@process_name}] Failed to start hutch instrumentation - #{e.message} - #{e.backtrace[0..4].join("\n")}"
@@ -67,6 +67,7 @@ module Bigcommerce
67
67
  server.add_type_collector(PrometheusExporter::Server::ActiveRecordCollector.new)
68
68
  server.add_type_collector(PrometheusExporter::Server::WebCollector.new)
69
69
  server.add_type_collector(PrometheusExporter::Server::PumaCollector.new)
70
+ ::Bigcommerce::Prometheus::Integrations::ActiveRecordSql.register_type_collector(server, process_name: @process_name)
70
71
  @type_collectors.each do |tc|
71
72
  server.add_type_collector(tc)
72
73
  end
@@ -78,6 +79,7 @@ module Bigcommerce
78
79
  @app.config.after_fork_callbacks = [] unless @app.config.after_fork_callbacks
79
80
  @app.config.after_fork_callbacks << lambda do
80
81
  ::Bigcommerce::Prometheus::Integrations::Puma.start(client: Bigcommerce::Prometheus.client)
82
+ ::Bigcommerce::Prometheus::Integrations::ActiveRecordSql.start_safe(client: Bigcommerce::Prometheus.client, process_name: @process_name)
81
83
  @collectors.each(&:start)
82
84
  rescue StandardError => e
83
85
  logger.error "[bigcommerce-prometheus][#{@process_name}] Failed to start web prometheus middleware after fork: #{e.message}"
@@ -0,0 +1,115 @@
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 Integrations
21
+ ##
22
+ # Subscribes to ActiveSupport sql.active_record notifications and pushes a per-operation
23
+ # SQL query duration histogram to the Prometheus exporter.
24
+ #
25
+ class ActiveRecordSql
26
+ IGNORED_NAMES = %w[SCHEMA CACHE].freeze
27
+ TYPE = 'active_record_sql'
28
+
29
+ # Idempotent: returns the same instance on repeated calls within a process,
30
+ # so calling .start more than once (e.g. from both the gem's instrumentor and a
31
+ # consuming app's initializer) does not register duplicate subscribers and
32
+ # double-count every SQL query.
33
+ #
34
+ # Noop when ActiveRecord is not loaded so non-Rails consumers (or any process that
35
+ # never loads ActiveRecord) can call this safely.
36
+ def self.start(client: nil)
37
+ return unless active_record_loaded?
38
+
39
+ @start ||= new(client: client || ::Bigcommerce::Prometheus.client).tap(&:subscribe!)
40
+ end
41
+
42
+ # @return [Boolean] whether ActiveRecord is loaded in the current process.
43
+ def self.active_record_loaded?
44
+ defined?(::ActiveRecord) ? true : false
45
+ end
46
+
47
+ # Wrapper for instrumentor wiring: registers the AR SQL type collector on the given server,
48
+ # gated on the active_record_enabled config flag, and swallows errors so an additive
49
+ # feature failure cannot take down core instrumentation.
50
+ def self.register_type_collector(server, process_name: nil)
51
+ return unless ::Bigcommerce::Prometheus.active_record_enabled
52
+
53
+ server.add_type_collector(::Bigcommerce::Prometheus::TypeCollectors::ActiveRecordSql.new)
54
+ rescue StandardError => e
55
+ log_warn(process_name, "Failed to register ActiveRecord type collector: #{e.message}")
56
+ end
57
+
58
+ # Wrapper for instrumentor wiring: starts the AR integration, gated on the
59
+ # active_record_enabled config flag, and swallows errors so an additive feature
60
+ # failure cannot take down core instrumentation.
61
+ def self.start_safe(client: nil, process_name: nil)
62
+ return unless ::Bigcommerce::Prometheus.active_record_enabled
63
+
64
+ start(client: client)
65
+ rescue StandardError => e
66
+ log_warn(process_name, "Failed to start ActiveRecord integration: #{e.message}")
67
+ end
68
+
69
+ def self.log_warn(process_name, message)
70
+ process_name ||= ::Bigcommerce::Prometheus.process_name
71
+ ::Bigcommerce::Prometheus.logger&.warn("[bigcommerce-prometheus][#{process_name}] #{message}")
72
+ end
73
+ private_class_method :log_warn
74
+
75
+ def initialize(client:)
76
+ @client = client
77
+ end
78
+
79
+ def subscribe!
80
+ ActiveSupport::Notifications.subscribe('sql.active_record') do |*args|
81
+ call(ActiveSupport::Notifications::Event.new(*args))
82
+ end
83
+ end
84
+
85
+ def call(event)
86
+ return if IGNORED_NAMES.include?(event.payload[:name])
87
+
88
+ @client.send_json(
89
+ type: TYPE,
90
+ duration_seconds: event.duration / 1000.0,
91
+ custom_labels: { operation: classify(event.payload[:sql]) }
92
+ )
93
+ rescue StandardError
94
+ # Never let metric instrumentation propagate into the request path.
95
+ nil
96
+ end
97
+
98
+ private
99
+
100
+ def classify(sql)
101
+ return 'other' if sql.nil?
102
+
103
+ first_token = sql.lstrip.split(/\s+/, 2).first&.upcase
104
+ case first_token
105
+ when 'SELECT' then 'select'
106
+ when 'INSERT' then 'insert'
107
+ when 'UPDATE' then 'update'
108
+ when 'DELETE' then 'delete'
109
+ else 'other'
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -51,7 +51,7 @@ module Bigcommerce
51
51
  # @return [Boolean]
52
52
  #
53
53
  def self.active_record_enabled?
54
- defined?(ActiveRecord) && ::ActiveRecord::Base.connection_pool.respond_to?(:stat)
54
+ defined?(::ActiveRecord) && ::ActiveRecord::Base.connection_pool.respond_to?(:stat)
55
55
  end
56
56
 
57
57
  ##
@@ -35,7 +35,7 @@ module Bigcommerce
35
35
  @prefix = (prefix || ::PrometheusExporter::DEFAULT_PREFIX).to_s
36
36
  @process_name = ::Bigcommerce::Prometheus.process_name
37
37
  @logger = logger || ::Bigcommerce::Prometheus.logger
38
- @server = ::Bigcommerce::Prometheus::Servers::Thin::Server.new(
38
+ @server = ::Bigcommerce::Prometheus::Servers::Puma::Server.new(
39
39
  port: @port,
40
40
  timeout: @timeout,
41
41
  logger: @logger,
@@ -52,12 +52,10 @@ module Bigcommerce
52
52
  def start
53
53
  @logger.info "[bigcommerce-prometheus][#{@process_name}] Starting prometheus exporter on port #{@host}:#{@port}"
54
54
 
55
- @run_thread = ::Thread.start do
56
- @server.start
57
- end
55
+ @run_thread = @server.run
58
56
  @running = true
59
57
 
60
- @logger.info "[bigcommerce-prometheus][#{@process_name}] Prometheus exporter started on #{@host}:#{@port} with #{@server.threadpool_size} threads"
58
+ @logger.info "[bigcommerce-prometheus][#{@process_name}] Prometheus exporter started on #{@host}:#{@port} with #{@server.max_threads} threads"
61
59
 
62
60
  @server
63
61
  rescue ::StandardError => e
@@ -81,7 +79,7 @@ module Bigcommerce
81
79
  # Stop the server
82
80
  #
83
81
  def stop
84
- @server.stop!
82
+ @server.stop
85
83
  @run_thread.kill
86
84
  @running = false
87
85
  $stdout.puts "[bigcommerce-prometheus][#{@process_name}] Prometheus exporter cleanly shut down"
@@ -18,16 +18,16 @@
18
18
  module Bigcommerce
19
19
  module Prometheus
20
20
  module Servers
21
- module Thin
21
+ module Puma
22
22
  module Controllers
23
23
  ##
24
- # Base thin controller for prometheus metrics
24
+ # Base puma controller for prometheus metrics
25
25
  #
26
26
  class BaseController
27
27
  ##
28
28
  # @param [Rack::Request] request
29
29
  # @param [Rack::Response] response
30
- # @param [Bigcommerce::Prometheus::Servers::Thin::ServerMetrics]
30
+ # @param [Bigcommerce::Prometheus::Servers::Puma::ServerMetrics]
31
31
  # @param [PrometheusExporter::Server::Collector] collector
32
32
  # @param [Logger] logger
33
33
  #
@@ -18,7 +18,7 @@
18
18
  module Bigcommerce
19
19
  module Prometheus
20
20
  module Servers
21
- module Thin
21
+ module Puma
22
22
  module Controllers
23
23
  ##
24
24
  # Handle 500s
@@ -22,7 +22,7 @@ require 'stringio'
22
22
  module Bigcommerce
23
23
  module Prometheus
24
24
  module Servers
25
- module Thin
25
+ module Puma
26
26
  module Controllers
27
27
  ##
28
28
  # GET /metrics
@@ -38,6 +38,8 @@ module Bigcommerce
38
38
  else
39
39
  @response.write(collected_metrics)
40
40
  end
41
+
42
+ set_header('Content-Type', 'text/plain; charset=utf-8')
41
43
  @response
42
44
  end
43
45
 
@@ -18,7 +18,7 @@
18
18
  module Bigcommerce
19
19
  module Prometheus
20
20
  module Servers
21
- module Thin
21
+ module Puma
22
22
  module Controllers
23
23
  ##
24
24
  # Handle invalid requests to server
@@ -18,7 +18,7 @@
18
18
  module Bigcommerce
19
19
  module Prometheus
20
20
  module Servers
21
- module Thin
21
+ module Puma
22
22
  module Controllers
23
23
  ##
24
24
  # POST /send-metrics
@@ -18,9 +18,9 @@
18
18
  module Bigcommerce
19
19
  module Prometheus
20
20
  module Servers
21
- module Thin
21
+ module Puma
22
22
  ##
23
- # Handles metrics requests as a Rack App on the Thin server
23
+ # Handles metrics requests as a Rack App on the Puma server
24
24
  #
25
25
  class RackApp
26
26
  ##
@@ -29,7 +29,7 @@ module Bigcommerce
29
29
  @timeout = timeout || ::Bigcommerce::Prometheus.server_timeout
30
30
  @collector = collector || ::PrometheusExporter::Server::Collector.new
31
31
  @logger = logger || ::Bigcommerce::Prometheus.logger
32
- @server_metrics = ::Bigcommerce::Prometheus::Servers::Thin::ServerMetrics.new(logger: @logger)
32
+ @server_metrics = ::Bigcommerce::Prometheus::Servers::Puma::ServerMetrics.new(logger: @logger)
33
33
  end
34
34
 
35
35
  def call(env)
@@ -39,7 +39,7 @@ module Bigcommerce
39
39
  handle(controller: controller, request: request, response: response)
40
40
  rescue StandardError => e
41
41
  @logger.error "Error: #{e.message}"
42
- handle(controller: ::Bigcommerce::Prometheus::Servers::Thin::Controllers::ErrorController, request: request, response: response)
42
+ handle(controller: ::Bigcommerce::Prometheus::Servers::Puma::Controllers::ErrorController, request: request, response: response)
43
43
  end
44
44
 
45
45
  ##
@@ -60,11 +60,11 @@ module Bigcommerce
60
60
  #
61
61
  def route(request)
62
62
  if request.fullpath == '/metrics' && request.request_method.to_s.downcase == 'get'
63
- Bigcommerce::Prometheus::Servers::Thin::Controllers::MetricsController
63
+ Bigcommerce::Prometheus::Servers::Puma::Controllers::MetricsController
64
64
  elsif request.fullpath == '/send-metrics' && request.request_method.to_s.downcase == 'post'
65
- Bigcommerce::Prometheus::Servers::Thin::Controllers::SendMetricsController
65
+ Bigcommerce::Prometheus::Servers::Puma::Controllers::SendMetricsController
66
66
  else
67
- Bigcommerce::Prometheus::Servers::Thin::Controllers::NotFoundController
67
+ Bigcommerce::Prometheus::Servers::Puma::Controllers::NotFoundController
68
68
  end
69
69
  end
70
70
 
@@ -18,20 +18,21 @@
18
18
  module Bigcommerce
19
19
  module Prometheus
20
20
  module Servers
21
- module Thin
21
+ module Puma
22
22
  ##
23
- # Thin adapter for server
23
+ # Puma adapter for server
24
24
  #
25
- class Server < ::Thin::Server
25
+ class Server < ::Puma::Server
26
26
  def initialize(port: nil, host: nil, timeout: nil, logger: nil, thread_pool_size: nil)
27
27
  @port = port || ::Bigcommerce::Prometheus.server_port
28
28
  @host = host || ::Bigcommerce::Prometheus.server_host
29
29
  @timeout = timeout || ::Bigcommerce::Prometheus.server_timeout
30
30
  @logger = logger || ::Bigcommerce::Prometheus.logger
31
- @rack_app = ::Bigcommerce::Prometheus::Servers::Thin::RackApp.new(timeout: timeout, logger: logger)
32
- super(@host, @port, @rack_app)
33
- ::Thin::Logging.logger = @logger
34
- self.threadpool_size = (thread_pool_size || ::Bigcommerce::Prometheus.server_thread_pool_size).to_i
31
+ @rack_app = ::Bigcommerce::Prometheus::Servers::Puma::RackApp.new(timeout: timeout, logger: logger)
32
+ thread_pool_size = (thread_pool_size || ::Bigcommerce::Prometheus.server_thread_pool_size).to_i
33
+ super(@rack_app, nil, max_threads: thread_pool_size)
34
+ add_tcp_listener(@host, @port)
35
+ @logger.info "[bigcommerce-prometheus] Prometheus server started on #{@host}:#{@port}"
35
36
  end
36
37
 
37
38
  ##
@@ -22,7 +22,7 @@ require 'stringio'
22
22
  module Bigcommerce
23
23
  module Prometheus
24
24
  module Servers
25
- module Thin
25
+ module Puma
26
26
  ##
27
27
  # Server metrics for the collector
28
28
  #
@@ -0,0 +1,53 @@
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
+ # Render-side counterpart to Integrations::ActiveRecordSql. Aggregates per-operation
23
+ # SQL query duration into a Prometheus Histogram exposed at /metrics.
24
+ #
25
+ class ActiveRecordSql < Bigcommerce::Prometheus::TypeCollectors::Base
26
+ def initialize(
27
+ default_labels: {},
28
+ buckets: [0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 20, 30, 60]
29
+ )
30
+ @buckets = buckets
31
+ super(type: Bigcommerce::Prometheus::Integrations::ActiveRecordSql::TYPE, default_labels: default_labels)
32
+ end
33
+
34
+ def build_metrics
35
+ {
36
+ sql_query_duration_seconds: PrometheusExporter::Metric::Histogram.new(
37
+ 'sql_query_duration_seconds',
38
+ 'ActiveRecord SQL query duration in seconds, labeled by operation.',
39
+ buckets: @buckets
40
+ )
41
+ }
42
+ end
43
+
44
+ def collect_metrics(data:, labels: {})
45
+ duration = data['duration_seconds']
46
+ return if duration.nil?
47
+
48
+ metric(:sql_query_duration_seconds).observe(duration.to_f, labels)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -17,6 +17,6 @@
17
17
  #
18
18
  module Bigcommerce
19
19
  module Prometheus
20
- VERSION = '0.6.0'
20
+ VERSION = '0.8.1'
21
21
  end
22
22
  end
@@ -22,7 +22,8 @@ require 'prometheus_exporter/server'
22
22
  require 'prometheus_exporter/client'
23
23
  require 'prometheus_exporter/middleware'
24
24
  require 'prometheus_exporter/instrumentation'
25
- require 'thin'
25
+ require 'puma'
26
+ require 'rack'
26
27
 
27
28
  require_relative 'prometheus/version'
28
29
  require_relative 'prometheus/loggable'
@@ -34,6 +35,8 @@ require_relative 'prometheus/collectors/base'
34
35
  require_relative 'prometheus/collectors/resque'
35
36
  require_relative 'prometheus/type_collectors/base'
36
37
  require_relative 'prometheus/type_collectors/resque'
38
+ require_relative 'prometheus/integrations/active_record'
39
+ require_relative 'prometheus/type_collectors/active_record'
37
40
 
38
41
  require_relative 'prometheus/instrumentors/web'
39
42
  require_relative 'prometheus/instrumentors/hutch'
@@ -42,14 +45,14 @@ require_relative 'prometheus/integrations/railtie' if defined?(Rails)
42
45
  require_relative 'prometheus/integrations/puma'
43
46
  require_relative 'prometheus/integrations/resque'
44
47
 
45
- require_relative 'prometheus/servers/thin/server'
46
- require_relative 'prometheus/servers/thin/rack_app'
47
- require_relative 'prometheus/servers/thin/server_metrics'
48
- require_relative 'prometheus/servers/thin/controllers/base_controller'
49
- require_relative 'prometheus/servers/thin/controllers/error_controller'
50
- require_relative 'prometheus/servers/thin/controllers/metrics_controller'
51
- require_relative 'prometheus/servers/thin/controllers/not_found_controller'
52
- require_relative 'prometheus/servers/thin/controllers/send_metrics_controller'
48
+ require_relative 'prometheus/servers/puma/server'
49
+ require_relative 'prometheus/servers/puma/rack_app'
50
+ require_relative 'prometheus/servers/puma/server_metrics'
51
+ require_relative 'prometheus/servers/puma/controllers/base_controller'
52
+ require_relative 'prometheus/servers/puma/controllers/error_controller'
53
+ require_relative 'prometheus/servers/puma/controllers/metrics_controller'
54
+ require_relative 'prometheus/servers/puma/controllers/not_found_controller'
55
+ require_relative 'prometheus/servers/puma/controllers/send_metrics_controller'
53
56
 
54
57
  module Bigcommerce
55
58
  ##
metadata CHANGED
@@ -1,155 +1,99 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bc-prometheus-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shaun McCormick
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-06 00:00:00.000000000 Z
11
+ date: 2026-05-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler-audit
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0.6'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0.6'
27
- - !ruby/object:Gem::Dependency
28
- name: pry
14
+ name: bigcommerce-multitrap
29
15
  requirement: !ruby/object:Gem::Requirement
30
16
  requirements:
31
- - - ">="
17
+ - - "~>"
32
18
  - !ruby/object:Gem::Version
33
- version: '0.12'
34
- type: :development
19
+ version: '0.1'
20
+ type: :runtime
35
21
  prerelease: false
36
22
  version_requirements: !ruby/object:Gem::Requirement
37
23
  requirements:
38
- - - ">="
24
+ - - "~>"
39
25
  - !ruby/object:Gem::Version
40
- version: '0.12'
26
+ version: '0.1'
41
27
  - !ruby/object:Gem::Dependency
42
- name: rake
28
+ name: prometheus_exporter
43
29
  requirement: !ruby/object:Gem::Requirement
44
30
  requirements:
45
- - - ">="
31
+ - - "~>"
46
32
  - !ruby/object:Gem::Version
47
- version: '10.0'
48
- type: :development
33
+ version: '0.7'
34
+ type: :runtime
49
35
  prerelease: false
50
36
  version_requirements: !ruby/object:Gem::Requirement
51
37
  requirements:
52
- - - ">="
38
+ - - "~>"
53
39
  - !ruby/object:Gem::Version
54
- version: '10.0'
40
+ version: '0.7'
55
41
  - !ruby/object:Gem::Dependency
56
- name: rspec
42
+ name: puma
57
43
  requirement: !ruby/object:Gem::Requirement
58
44
  requirements:
59
- - - ">="
45
+ - - ">"
60
46
  - !ruby/object:Gem::Version
61
- version: '3.8'
62
- type: :development
47
+ version: '5'
48
+ type: :runtime
63
49
  prerelease: false
64
50
  version_requirements: !ruby/object:Gem::Requirement
65
51
  requirements:
66
- - - ">="
52
+ - - ">"
67
53
  - !ruby/object:Gem::Version
68
- version: '3.8'
54
+ version: '5'
69
55
  - !ruby/object:Gem::Dependency
70
- name: rspec_junit_formatter
56
+ name: rack
71
57
  requirement: !ruby/object:Gem::Requirement
72
58
  requirements:
73
59
  - - ">="
74
60
  - !ruby/object:Gem::Version
75
- version: '0.4'
76
- type: :development
61
+ version: '3.0'
62
+ type: :runtime
77
63
  prerelease: false
78
64
  version_requirements: !ruby/object:Gem::Requirement
79
65
  requirements:
80
66
  - - ">="
81
67
  - !ruby/object:Gem::Version
82
- version: '0.4'
68
+ version: '3.0'
83
69
  - !ruby/object:Gem::Dependency
84
- name: rubocop
70
+ name: rake
85
71
  requirement: !ruby/object:Gem::Requirement
86
72
  requirements:
87
73
  - - ">="
88
74
  - !ruby/object:Gem::Version
89
- version: '1.0'
90
- type: :development
75
+ version: '10.0'
76
+ type: :runtime
91
77
  prerelease: false
92
78
  version_requirements: !ruby/object:Gem::Requirement
93
79
  requirements:
94
80
  - - ">="
95
81
  - !ruby/object:Gem::Version
96
- version: '1.0'
82
+ version: '10.0'
97
83
  - !ruby/object:Gem::Dependency
98
- name: simplecov
84
+ name: activesupport
99
85
  requirement: !ruby/object:Gem::Requirement
100
86
  requirements:
101
87
  - - ">="
102
88
  - !ruby/object:Gem::Version
103
- version: '0.16'
89
+ version: '6.0'
104
90
  type: :development
105
91
  prerelease: false
106
92
  version_requirements: !ruby/object:Gem::Requirement
107
93
  requirements:
108
94
  - - ">="
109
95
  - !ruby/object:Gem::Version
110
- version: '0.16'
111
- - !ruby/object:Gem::Dependency
112
- name: bigcommerce-multitrap
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - "~>"
116
- - !ruby/object:Gem::Version
117
- version: '0.1'
118
- type: :runtime
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - "~>"
123
- - !ruby/object:Gem::Version
124
- version: '0.1'
125
- - !ruby/object:Gem::Dependency
126
- name: prometheus_exporter
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - "~>"
130
- - !ruby/object:Gem::Version
131
- version: '0.7'
132
- type: :runtime
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - "~>"
137
- - !ruby/object:Gem::Version
138
- version: '0.7'
139
- - !ruby/object:Gem::Dependency
140
- name: thin
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - "~>"
144
- - !ruby/object:Gem::Version
145
- version: '1.7'
146
- type: :runtime
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - "~>"
151
- - !ruby/object:Gem::Version
152
- version: '1.7'
96
+ version: '6.0'
153
97
  description: Simple integration of ruby and puma servers with prometheus
154
98
  email:
155
99
  - shaun.mccormick@bigcommerce.com
@@ -169,19 +113,21 @@ files:
169
113
  - lib/bigcommerce/prometheus/instrumentors/hutch.rb
170
114
  - lib/bigcommerce/prometheus/instrumentors/resque.rb
171
115
  - lib/bigcommerce/prometheus/instrumentors/web.rb
116
+ - lib/bigcommerce/prometheus/integrations/active_record.rb
172
117
  - lib/bigcommerce/prometheus/integrations/puma.rb
173
118
  - lib/bigcommerce/prometheus/integrations/railtie.rb
174
119
  - lib/bigcommerce/prometheus/integrations/resque.rb
175
120
  - lib/bigcommerce/prometheus/loggable.rb
176
121
  - lib/bigcommerce/prometheus/server.rb
177
- - lib/bigcommerce/prometheus/servers/thin/controllers/base_controller.rb
178
- - lib/bigcommerce/prometheus/servers/thin/controllers/error_controller.rb
179
- - lib/bigcommerce/prometheus/servers/thin/controllers/metrics_controller.rb
180
- - lib/bigcommerce/prometheus/servers/thin/controllers/not_found_controller.rb
181
- - lib/bigcommerce/prometheus/servers/thin/controllers/send_metrics_controller.rb
182
- - lib/bigcommerce/prometheus/servers/thin/rack_app.rb
183
- - lib/bigcommerce/prometheus/servers/thin/server.rb
184
- - lib/bigcommerce/prometheus/servers/thin/server_metrics.rb
122
+ - lib/bigcommerce/prometheus/servers/puma/controllers/base_controller.rb
123
+ - lib/bigcommerce/prometheus/servers/puma/controllers/error_controller.rb
124
+ - lib/bigcommerce/prometheus/servers/puma/controllers/metrics_controller.rb
125
+ - lib/bigcommerce/prometheus/servers/puma/controllers/not_found_controller.rb
126
+ - lib/bigcommerce/prometheus/servers/puma/controllers/send_metrics_controller.rb
127
+ - lib/bigcommerce/prometheus/servers/puma/rack_app.rb
128
+ - lib/bigcommerce/prometheus/servers/puma/server.rb
129
+ - lib/bigcommerce/prometheus/servers/puma/server_metrics.rb
130
+ - lib/bigcommerce/prometheus/type_collectors/active_record.rb
185
131
  - lib/bigcommerce/prometheus/type_collectors/base.rb
186
132
  - lib/bigcommerce/prometheus/type_collectors/resque.rb
187
133
  - lib/bigcommerce/prometheus/version.rb
@@ -197,14 +143,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
197
143
  requirements:
198
144
  - - ">="
199
145
  - !ruby/object:Gem::Version
200
- version: '3.0'
146
+ version: '3.2'
201
147
  required_rubygems_version: !ruby/object:Gem::Requirement
202
148
  requirements:
203
149
  - - ">="
204
150
  - !ruby/object:Gem::Version
205
151
  version: '0'
206
152
  requirements: []
207
- rubygems_version: 3.4.1
153
+ rubygems_version: 3.5.7
208
154
  signing_key:
209
155
  specification_version: 4
210
156
  summary: Simple integration of ruby and puma servers with prometheus