Module: ScoutApm::Instruments::ActiveRecordQueryingInstruments

Defined in:
lib/scout_apm/instruments/active_record.rb

Overview

Entry-point of instruments.

Instrumentation starts in ActiveRecord::Relation#exec_queries (Rails >= 3.2.0) or ActiveRecord::FinderMethods#find_with_assocations (previous Rails versions).

ActiveRecord::Querying#find_by_sql is instrumented in all Rails versions even though it is also invoked by #exec_queries/#find_by_associations because it can be invoked directly from user code (e.g., Post.find_by_sql(“SELECT * FROM posts”)). The layer started by #exec_queries/#find_by_assocations is marked to ignore children, so it will not cause duplicate layers in the former case.

These methods are early in the chain of calls invoked when executing an ActiveRecord query, before the cache is consulted. If the query is later determined to be a cache miss, ‘#log` will be invoked, which we also instrument, and more details will be filled in (name, sql).

Caveats:

* We don't have a name for the query yet.
* The query hasn't hit the cache yet. In the case of a cache hit, we
  won't hit #log, so won't get a name, leaving the misleading default.
* One call here can result in several calls to #log, especially in the
  case where Rails needs to load the schema details for the table being
  queried.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(instrumented_class) ⇒ Object



303
304
305
306
307
308
309
310
311
# File 'lib/scout_apm/instruments/active_record.rb', line 303

def self.included(instrumented_class)
  ScoutApm::Agent.instance.context.logger.info "Instrumenting ActiveRecord::Querying - #{instrumented_class.inspect}"
  instrumented_class.class_eval do
    unless instrumented_class.method_defined?(:find_by_sql_without_scout_instruments)
      alias_method :find_by_sql_without_scout_instruments, :find_by_sql
      alias_method :find_by_sql, :find_by_sql_with_scout_instruments
    end
  end
end

Instance Method Details

#find_by_sql_with_scout_instruments(*args, **kwargs, &block) ⇒ Object



313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
# File 'lib/scout_apm/instruments/active_record.rb', line 313

def find_by_sql_with_scout_instruments(*args, **kwargs, &block)
  req = ScoutApm::RequestManager.lookup
  layer = ScoutApm::Layer.new("ActiveRecord", Utils::ActiveRecordMetricName::DEFAULT_METRIC)
  layer.annotate_layer(:ignorable => true)
  req.start_layer(layer)
  req.ignore_children!
  begin
    if ScoutApm::Agent.instance.context.environment.supports_kwarg_delegation?
      find_by_sql_without_scout_instruments(*args, **kwargs, &block)
    else
      find_by_sql_without_scout_instruments(*args, &block)
    end
  ensure
    req.acknowledge_children!
    req.stop_layer
  end
end