Module: NewRelic::Agent::Instrumentation::ActiveRecord

Defined in:
lib/new_relic/agent/instrumentation/active_record.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(instrumented_class) ⇒ Object



5
6
7
8
9
10
11
12
13
# File 'lib/new_relic/agent/instrumentation/active_record.rb', line 5

def self.included(instrumented_class)
  instrumented_class.class_eval do
    unless instrumented_class.method_defined?(:log_without_newrelic_instrumentation)
      alias_method :log_without_newrelic_instrumentation, :log
      alias_method :log, :log_with_newrelic_instrumentation
      protected :log
    end
  end
end

Instance Method Details

#log_with_newrelic_instrumentation(*args, &block) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/new_relic/agent/instrumentation/active_record.rb', line 15

def log_with_newrelic_instrumentation(*args, &block)
  if !NewRelic::Agent.is_execution_traced?
    return log_without_newrelic_instrumentation(*args, &block)
  end
  
  sql, name, binds = args
  metric = metric_for_name(NewRelic::Helper.correctly_encoded(name)) ||
    metric_for_sql(NewRelic::Helper.correctly_encoded(sql))
  
  if !metric
    log_without_newrelic_instrumentation(*args, &block)
  else
    metrics = [metric, remote_service_metric].compact
    metrics += rollup_metrics_for(metric)
    self.class.trace_execution_scoped(metrics) do
      t0 = Time.now
      begin
        log_without_newrelic_instrumentation(*args, &block)
      ensure
        elapsed_time = (Time.now - t0).to_f
        NewRelic::Agent.instance.transaction_sampler.notice_sql(sql,
                                                 @config, elapsed_time)
        NewRelic::Agent.instance.sql_sampler.notice_sql(sql, metric,
                                                 @config, elapsed_time)
      end
    end
  end
end

#metric_for_name(name) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/new_relic/agent/instrumentation/active_record.rb', line 52

def metric_for_name(name)
  if name && (parts = name.split " ") && parts.size == 2
    model = parts.first
    operation = parts.last.downcase
    op_name = case operation
                  when 'load', 'count', 'exists' then 'find'
                  when 'indexes', 'columns' then nil # fall back to DirectSQL
                  when 'destroy', 'find', 'save', 'create' then operation
                  when 'update' then 'save'
                  else
                    if model == 'Join'
                      operation
                    end
                  end
    "ActiveRecord/#{model}/#{op_name}" if op_name
  end
end

#metric_for_sql(sql) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/new_relic/agent/instrumentation/active_record.rb', line 70

def metric_for_sql(sql)
  metric = NewRelic::Agent::Instrumentation::MetricFrame.database_metric_name
  if metric.nil?
    if sql =~ /^(select|update|insert|delete|show)/i
      # Could not determine the model/operation so let's find a better
      # metric.  If it doesn't match the regex, it's probably a show
      # command or some DDL which we'll ignore.
      metric = "Database/SQL/#{$1.downcase}"
    else
      metric = "Database/SQL/other"
    end
  end
  metric
end

#remote_service_metricObject



44
45
46
47
48
49
50
# File 'lib/new_relic/agent/instrumentation/active_record.rb', line 44

def remote_service_metric
  if @config && @config[:adapter]
    type = @config[:adapter].sub(/\d*/, '')
    host = @config[:host] || 'localhost'
    "RemoteService/sql/#{type}/#{host}"
  end                      
end

#rollup_metrics_for(metric) ⇒ Object



85
86
87
88
89
# File 'lib/new_relic/agent/instrumentation/active_record.rb', line 85

def rollup_metrics_for(metric)
  metrics = ["ActiveRecord/all"]
  metrics << "ActiveRecord/#{$1}" if metric =~ /ActiveRecord\/\w+\/(\w+)/
  metrics
end