Class: Bigcommerce::Prometheus::Integrations::ActiveRecordSql
- Inherits:
-
Object
- Object
- Bigcommerce::Prometheus::Integrations::ActiveRecordSql
- Defined in:
- lib/bigcommerce/prometheus/integrations/active_record.rb
Overview
Subscribes to ActiveSupport sql.active_record notifications and pushes a per-operation SQL query duration histogram to the Prometheus exporter.
Constant Summary collapse
- IGNORED_NAMES =
%w[SCHEMA CACHE].freeze
- TYPE =
'active_record_sql'
Class Method Summary collapse
-
.active_record_loaded? ⇒ Boolean
Whether ActiveRecord is loaded in the current process.
-
.register_type_collector(server, process_name: nil) ⇒ Object
Wrapper for instrumentor wiring: registers the AR SQL type collector on the given server, gated on the active_record_enabled config flag, and swallows errors so an additive feature failure cannot take down core instrumentation.
-
.start(client: nil) ⇒ Object
Idempotent: returns the same instance on repeated calls within a process, so calling .start more than once (e.g. from both the gem’s instrumentor and a consuming app’s initializer) does not register duplicate subscribers and double-count every SQL query.
-
.start_safe(client: nil, process_name: nil) ⇒ Object
Wrapper for instrumentor wiring: starts the AR integration, gated on the active_record_enabled config flag, and swallows errors so an additive feature failure cannot take down core instrumentation.
Instance Method Summary collapse
- #call(event) ⇒ Object
-
#initialize(client:) ⇒ ActiveRecordSql
constructor
A new instance of ActiveRecordSql.
- #subscribe! ⇒ Object
Constructor Details
#initialize(client:) ⇒ ActiveRecordSql
Returns a new instance of ActiveRecordSql.
75 76 77 |
# File 'lib/bigcommerce/prometheus/integrations/active_record.rb', line 75 def initialize(client:) @client = client end |
Class Method Details
.active_record_loaded? ⇒ Boolean
Returns whether ActiveRecord is loaded in the current process.
43 44 45 |
# File 'lib/bigcommerce/prometheus/integrations/active_record.rb', line 43 def self.active_record_loaded? defined?(::ActiveRecord) ? true : false end |
.register_type_collector(server, process_name: nil) ⇒ Object
Wrapper for instrumentor wiring: registers the AR SQL type collector on the given server, gated on the active_record_enabled config flag, and swallows errors so an additive feature failure cannot take down core instrumentation.
50 51 52 53 54 55 56 |
# File 'lib/bigcommerce/prometheus/integrations/active_record.rb', line 50 def self.register_type_collector(server, process_name: nil) return unless ::Bigcommerce::Prometheus.active_record_enabled server.add_type_collector(::Bigcommerce::Prometheus::TypeCollectors::ActiveRecordSql.new) rescue StandardError => e log_warn(process_name, "Failed to register ActiveRecord type collector: #{e.}") end |
.start(client: nil) ⇒ Object
Idempotent: returns the same instance on repeated calls within a process, so calling .start more than once (e.g. from both the gem’s instrumentor and a consuming app’s initializer) does not register duplicate subscribers and double-count every SQL query.
Noop when ActiveRecord is not loaded so non-Rails consumers (or any process that never loads ActiveRecord) can call this safely.
36 37 38 39 40 |
# File 'lib/bigcommerce/prometheus/integrations/active_record.rb', line 36 def self.start(client: nil) return unless active_record_loaded? @start ||= new(client: client || ::Bigcommerce::Prometheus.client).tap(&:subscribe!) end |
.start_safe(client: nil, process_name: nil) ⇒ Object
Wrapper for instrumentor wiring: starts the AR integration, gated on the active_record_enabled config flag, and swallows errors so an additive feature failure cannot take down core instrumentation.
61 62 63 64 65 66 67 |
# File 'lib/bigcommerce/prometheus/integrations/active_record.rb', line 61 def self.start_safe(client: nil, process_name: nil) return unless ::Bigcommerce::Prometheus.active_record_enabled start(client: client) rescue StandardError => e log_warn(process_name, "Failed to start ActiveRecord integration: #{e.}") end |
Instance Method Details
#call(event) ⇒ Object
85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/bigcommerce/prometheus/integrations/active_record.rb', line 85 def call(event) return if IGNORED_NAMES.include?(event.payload[:name]) @client.send_json( type: TYPE, duration_seconds: event.duration / 1000.0, custom_labels: { operation: classify(event.payload[:sql]) } ) rescue StandardError # Never let metric instrumentation propagate into the request path. nil end |
#subscribe! ⇒ Object
79 80 81 82 83 |
# File 'lib/bigcommerce/prometheus/integrations/active_record.rb', line 79 def subscribe! ActiveSupport::Notifications.subscribe('sql.active_record') do |*args| call(ActiveSupport::Notifications::Event.new(*args)) end end |