Class: NewRelic::Agent::SqlSampler

Inherits:
Object
  • Object
show all
Defined in:
lib/new_relic/agent/sql_sampler.rb

Defined Under Namespace

Modules: Shim

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSqlSampler

Returns a new instance of SqlSampler.



20
21
22
23
24
25
26
27
28
29
# File 'lib/new_relic/agent/sql_sampler.rb', line 20

def initialize
  configure!
  @sql_traces = {}
  clear_transaction_data

  # This lock is used to synchronize access to the @last_sample
  # and related variables. It can become necessary on JRuby or
  # any 'honest-to-god'-multithreaded system
  @samples_lock = Mutex.new
end

Instance Attribute Details

#disabledObject (readonly)

Returns the value of attribute disabled.



15
16
17
# File 'lib/new_relic/agent/sql_sampler.rb', line 15

def disabled
  @disabled
end

#sql_tracesObject (readonly)

this is for unit tests only



18
19
20
# File 'lib/new_relic/agent/sql_sampler.rb', line 18

def sql_traces
  @sql_traces
end

Class Method Details

.configObject



51
52
53
54
55
56
57
58
59
60
# File 'lib/new_relic/agent/sql_sampler.rb', line 51

def self.config
  control = NewRelic::Control.instance
  txn_config = control.fetch('transaction_tracer', {})

  if txn_config.fetch('enabled', true) && control.has_slow_sql_config?
    txn_config['enabled'] = control['slow_sql']['enabled']
  end
  
  txn_config
end

Instance Method Details

#clear_transaction_dataObject



97
98
99
# File 'lib/new_relic/agent/sql_sampler.rb', line 97

def clear_transaction_data
  Thread.current[:new_relic_sql_data] = nil
end

#configObject



47
48
49
# File 'lib/new_relic/agent/sql_sampler.rb', line 47

def config
  self.class.config
end

#configure!Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/new_relic/agent/sql_sampler.rb', line 31

def configure!
  @explain_threshold = config.fetch('explain_threshold', 0.5).to_f
  @explain_enabled = config.fetch('explain_enabled', true)
  @stack_trace_threshold = config.fetch('stack_trace_threshold',
                                        0.5).to_f
  if config.fetch('enabled', true) &&
      NewRelic::Control.instance['transaction_tracer'] &&
      NewRelic::Control.instance['transaction_tracer'].fetch('enabled',
                                                             true) &&
      NewRelic::Control.instance.fetch('collect_traces', true)
    enable
  else
    disable
  end
end

#create_transaction_dataObject



89
90
91
# File 'lib/new_relic/agent/sql_sampler.rb', line 89

def create_transaction_data
  Thread.current[:new_relic_sql_data] = TransactionSqlData.new
end

#disableObject

Disable the sql sampler - this also deregisters it with the statistics engine.



70
71
72
# File 'lib/new_relic/agent/sql_sampler.rb', line 70

def disable
  @disabled = true
end

#enableObject

Enable the sql sampler - this also registers it with the statistics engine.



64
65
66
# File 'lib/new_relic/agent/sql_sampler.rb', line 64

def enable
  @disabled = false
end

#enabled?Boolean

Returns:

  • (Boolean)


74
75
76
# File 'lib/new_relic/agent/sql_sampler.rb', line 74

def enabled?
  !@disabled
end

#harvestObject



149
150
151
152
153
154
155
156
157
158
159
# File 'lib/new_relic/agent/sql_sampler.rb', line 149

def harvest
  return [] if disabled
  result = []
  @samples_lock.synchronize do
    result = @sql_traces.values
    @sql_traces = {}
  end        
  slowest = result.sort{|a,b| b.max_call_time <=> a.max_call_time}[0,10]
  slowest.each {|trace| trace.prepare_to_send }
  slowest
end

#harvest_slow_sql(transaction_sql_data) ⇒ Object

this should always be called under the @samples_lock



116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/new_relic/agent/sql_sampler.rb', line 116

def harvest_slow_sql(transaction_sql_data)
  transaction_sql_data.sql_data.each do |sql_item|
    normalized_sql = sql_item.normalize
    sql_trace = @sql_traces[normalized_sql]
    if sql_trace
      sql_trace.aggregate(sql_item, transaction_sql_data.path,
                          transaction_sql_data.uri)
    else
      @sql_traces[normalized_sql] = SqlTrace.new(normalized_sql,
          sql_item, transaction_sql_data.path, transaction_sql_data.uri)
    end
  end

end

#merge(sql_traces) ⇒ Object



142
143
144
145
146
147
# File 'lib/new_relic/agent/sql_sampler.rb', line 142

def merge(sql_traces)
  @samples_lock.synchronize do
#FIXME we need to merge the sql_traces array back into the @sql_traces hash
#          @sql_traces.merge! sql_traces
  end
end

#notice_first_scope_push(time) ⇒ Object



85
86
87
# File 'lib/new_relic/agent/sql_sampler.rb', line 85

def notice_first_scope_push(time)
  create_transaction_data
end

#notice_scope_empty(time = Time.now) ⇒ Object

This is called when we are done with the transaction.



102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/new_relic/agent/sql_sampler.rb', line 102

def notice_scope_empty(time=Time.now)
  data = transaction_data
  clear_transaction_data

  if data.sql_data.size > 0
    @samples_lock.synchronize do
      NewRelic::Agent.instance.log.debug "Harvesting #{data.sql_data.size} slow transaction sql statement(s)"
      #FIXME get tx name and uri
      harvest_slow_sql data
    end
  end
end

#notice_sql(sql, metric_name, config, duration) ⇒ Object



131
132
133
134
135
136
137
138
139
140
# File 'lib/new_relic/agent/sql_sampler.rb', line 131

def notice_sql(sql, metric_name, config, duration)
  return unless transaction_data
  if NewRelic::Agent.is_sql_recorded?
    if duration > @explain_threshold
      backtrace = caller.join("\n")
      transaction_data.sql_data << SlowSql.new(sql, metric_name, config,
                                               duration, backtrace)
    end
  end
end

#notice_transaction(path, uri = nil, params = {}) ⇒ Object



78
79
80
81
82
83
# File 'lib/new_relic/agent/sql_sampler.rb', line 78

def notice_transaction(path, uri=nil, params={})
  if NewRelic::Agent.instance.transaction_sampler.builder
    guid = NewRelic::Agent.instance.transaction_sampler.builder.sample.guid
  end
  transaction_data.set_transaction_info(path, uri, params, guid) if !disabled && transaction_data
end

#reset!Object

reset samples without rebooting the web server



162
163
# File 'lib/new_relic/agent/sql_sampler.rb', line 162

def reset!
end

#transaction_dataObject



93
94
95
# File 'lib/new_relic/agent/sql_sampler.rb', line 93

def transaction_data
  Thread.current[:new_relic_sql_data]
end