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 +4 -4
- data/CHANGELOG.md +16 -4
- data/README.md +8 -0
- data/bc-prometheus-ruby.gemspec +6 -10
- data/lib/bigcommerce/prometheus/client.rb +8 -0
- data/lib/bigcommerce/prometheus/configuration.rb +2 -1
- data/lib/bigcommerce/prometheus/instrumentors/hutch.rb +2 -0
- data/lib/bigcommerce/prometheus/instrumentors/web.rb +2 -0
- data/lib/bigcommerce/prometheus/integrations/active_record.rb +115 -0
- data/lib/bigcommerce/prometheus/integrations/puma.rb +1 -1
- data/lib/bigcommerce/prometheus/server.rb +4 -6
- data/lib/bigcommerce/prometheus/servers/{thin → puma}/controllers/base_controller.rb +3 -3
- data/lib/bigcommerce/prometheus/servers/{thin → puma}/controllers/error_controller.rb +1 -1
- data/lib/bigcommerce/prometheus/servers/{thin → puma}/controllers/metrics_controller.rb +3 -1
- data/lib/bigcommerce/prometheus/servers/{thin → puma}/controllers/not_found_controller.rb +1 -1
- data/lib/bigcommerce/prometheus/servers/{thin → puma}/controllers/send_metrics_controller.rb +1 -1
- data/lib/bigcommerce/prometheus/servers/{thin → puma}/rack_app.rb +7 -7
- data/lib/bigcommerce/prometheus/servers/{thin → puma}/server.rb +8 -7
- data/lib/bigcommerce/prometheus/servers/{thin → puma}/server_metrics.rb +1 -1
- data/lib/bigcommerce/prometheus/type_collectors/active_record.rb +53 -0
- data/lib/bigcommerce/prometheus/version.rb +1 -1
- data/lib/bigcommerce/prometheus.rb +12 -9
- metadata +43 -97
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a7a2ca2f975be9d346e217c4a13e4ca702a573889383c43292094f66aa82c562
|
|
4
|
+
data.tar.gz: 2724f8826c1ee9d668357676834f15dc24836ed1d05337f7b217133119fb4e26
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
data/bc-prometheus-ruby.gemspec
CHANGED
|
@@ -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.
|
|
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 '
|
|
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::
|
|
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 =
|
|
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.
|
|
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
|
|
21
|
+
module Puma
|
|
22
22
|
module Controllers
|
|
23
23
|
##
|
|
24
|
-
# Base
|
|
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::
|
|
30
|
+
# @param [Bigcommerce::Prometheus::Servers::Puma::ServerMetrics]
|
|
31
31
|
# @param [PrometheusExporter::Server::Collector] collector
|
|
32
32
|
# @param [Logger] logger
|
|
33
33
|
#
|
|
@@ -22,7 +22,7 @@ require 'stringio'
|
|
|
22
22
|
module Bigcommerce
|
|
23
23
|
module Prometheus
|
|
24
24
|
module Servers
|
|
25
|
-
module
|
|
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,9 +18,9 @@
|
|
|
18
18
|
module Bigcommerce
|
|
19
19
|
module Prometheus
|
|
20
20
|
module Servers
|
|
21
|
-
module
|
|
21
|
+
module Puma
|
|
22
22
|
##
|
|
23
|
-
# Handles metrics requests as a Rack App on the
|
|
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::
|
|
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::
|
|
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::
|
|
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::
|
|
65
|
+
Bigcommerce::Prometheus::Servers::Puma::Controllers::SendMetricsController
|
|
66
66
|
else
|
|
67
|
-
Bigcommerce::Prometheus::Servers::
|
|
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
|
|
21
|
+
module Puma
|
|
22
22
|
##
|
|
23
|
-
#
|
|
23
|
+
# Puma adapter for server
|
|
24
24
|
#
|
|
25
|
-
class 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::
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
##
|
|
@@ -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
|
|
@@ -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 '
|
|
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/
|
|
46
|
-
require_relative 'prometheus/servers/
|
|
47
|
-
require_relative 'prometheus/servers/
|
|
48
|
-
require_relative 'prometheus/servers/
|
|
49
|
-
require_relative 'prometheus/servers/
|
|
50
|
-
require_relative 'prometheus/servers/
|
|
51
|
-
require_relative 'prometheus/servers/
|
|
52
|
-
require_relative 'prometheus/servers/
|
|
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.
|
|
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:
|
|
11
|
+
date: 2026-05-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
|
-
name:
|
|
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.
|
|
34
|
-
type: :
|
|
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.
|
|
26
|
+
version: '0.1'
|
|
41
27
|
- !ruby/object:Gem::Dependency
|
|
42
|
-
name:
|
|
28
|
+
name: prometheus_exporter
|
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
|
44
30
|
requirements:
|
|
45
|
-
- - "
|
|
31
|
+
- - "~>"
|
|
46
32
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '
|
|
48
|
-
type: :
|
|
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: '
|
|
40
|
+
version: '0.7'
|
|
55
41
|
- !ruby/object:Gem::Dependency
|
|
56
|
-
name:
|
|
42
|
+
name: puma
|
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
|
58
44
|
requirements:
|
|
59
|
-
- - "
|
|
45
|
+
- - ">"
|
|
60
46
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: '
|
|
62
|
-
type: :
|
|
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: '
|
|
54
|
+
version: '5'
|
|
69
55
|
- !ruby/object:Gem::Dependency
|
|
70
|
-
name:
|
|
56
|
+
name: rack
|
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
|
72
58
|
requirements:
|
|
73
59
|
- - ">="
|
|
74
60
|
- !ruby/object:Gem::Version
|
|
75
|
-
version: '0
|
|
76
|
-
type: :
|
|
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
|
|
68
|
+
version: '3.0'
|
|
83
69
|
- !ruby/object:Gem::Dependency
|
|
84
|
-
name:
|
|
70
|
+
name: rake
|
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
|
86
72
|
requirements:
|
|
87
73
|
- - ">="
|
|
88
74
|
- !ruby/object:Gem::Version
|
|
89
|
-
version: '
|
|
90
|
-
type: :
|
|
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: '
|
|
82
|
+
version: '10.0'
|
|
97
83
|
- !ruby/object:Gem::Dependency
|
|
98
|
-
name:
|
|
84
|
+
name: activesupport
|
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
|
100
86
|
requirements:
|
|
101
87
|
- - ">="
|
|
102
88
|
- !ruby/object:Gem::Version
|
|
103
|
-
version: '0
|
|
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
|
|
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/
|
|
178
|
-
- lib/bigcommerce/prometheus/servers/
|
|
179
|
-
- lib/bigcommerce/prometheus/servers/
|
|
180
|
-
- lib/bigcommerce/prometheus/servers/
|
|
181
|
-
- lib/bigcommerce/prometheus/servers/
|
|
182
|
-
- lib/bigcommerce/prometheus/servers/
|
|
183
|
-
- lib/bigcommerce/prometheus/servers/
|
|
184
|
-
- lib/bigcommerce/prometheus/servers/
|
|
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.
|
|
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.
|
|
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
|