Class: NewRelic::Agent::TransactionSampler
- Inherits:
-
Object
- Object
- NewRelic::Agent::TransactionSampler
- Defined in:
- lib/new_relic/agent/transaction_sampler.rb
Defined Under Namespace
Modules: Shim
Constant Summary collapse
- BUILDER_KEY =
:transaction_sample_builder
- MAX_SQL_LENGTH =
some statements (particularly INSERTS with large BLOBS may be very large; we should trim them to a maximum usable length config is the driver configuration for the connection
16384
Instance Attribute Summary collapse
-
#disabled ⇒ Object
readonly
Returns the value of attribute disabled.
-
#last_sample ⇒ Object
readonly
Returns the value of attribute last_sample.
-
#random_sampling ⇒ Object
Returns the value of attribute random_sampling.
-
#samples ⇒ Object
readonly
Returns the value of attribute samples.
-
#sampling_rate ⇒ Object
Returns the value of attribute sampling_rate.
-
#stack_trace_threshold ⇒ Object
Returns the value of attribute stack_trace_threshold.
Instance Method Summary collapse
- #current_sample_id ⇒ Object
- #disable ⇒ Object
-
#harvest(previous = nil, slow_threshold = 2.0) ⇒ Object
get the set of collected samples, merging into previous samples, and clear the collected sample list.
- #ignore_transaction ⇒ Object
-
#initialize ⇒ TransactionSampler
constructor
A new instance of TransactionSampler.
- #notice_first_scope_push(time) ⇒ Object
- #notice_pop_scope(scope, time = Time.now.to_f) ⇒ Object
- #notice_profile(profile) ⇒ Object
- #notice_push_scope(scope, time = Time.now.to_f) ⇒ Object
-
#notice_scope_empty(time = Time.now.to_f) ⇒ Object
This is called when we are done with the transaction.
- #notice_sql(sql, config, duration) ⇒ Object
- #notice_transaction(path, uri = nil, params = {}) ⇒ Object
- #notice_transaction_cpu_time(cpu_time) ⇒ Object
-
#reset! ⇒ Object
reset samples without rebooting the web server.
- #scope_depth ⇒ Object
Constructor Details
#initialize ⇒ TransactionSampler
Returns a new instance of TransactionSampler.
19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 19 def initialize @samples = [] @harvest_count = 0 @max_samples = 100 @random_sample = nil config = NewRelic::Control.instance sampler_config = config.fetch('transaction_tracer', {}) @segment_limit = sampler_config.fetch('limit_segments', 4000) @stack_trace_threshold = sampler_config.fetch('stack_trace_threshold', 0.500).to_f @samples_lock = Mutex.new end |
Instance Attribute Details
#disabled ⇒ Object (readonly)
Returns the value of attribute disabled.
17 18 19 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 17 def disabled @disabled end |
#last_sample ⇒ Object (readonly)
Returns the value of attribute last_sample.
17 18 19 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 17 def last_sample @last_sample end |
#random_sampling ⇒ Object
Returns the value of attribute random_sampling.
16 17 18 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 16 def random_sampling @random_sampling end |
#samples ⇒ Object (readonly)
Returns the value of attribute samples.
17 18 19 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 17 def samples @samples end |
#sampling_rate ⇒ Object
Returns the value of attribute sampling_rate.
16 17 18 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 16 def sampling_rate @sampling_rate end |
#stack_trace_threshold ⇒ Object
Returns the value of attribute stack_trace_threshold.
16 17 18 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 16 def stack_trace_threshold @stack_trace_threshold end |
Instance Method Details
#current_sample_id ⇒ Object
31 32 33 34 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 31 def current_sample_id b=builder b and b.sample_id end |
#disable ⇒ Object
36 37 38 39 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 36 def disable @disabled = true NewRelic::Agent.instance.stats_engine.remove_transaction_sampler self end |
#harvest(previous = nil, slow_threshold = 2.0) ⇒ Object
get the set of collected samples, merging into previous samples, and clear the collected sample list.
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 155 def harvest(previous = nil, slow_threshold = 2.0) return [] if disabled result = [] previous ||= [] previous = [previous] unless previous.is_a?(Array) previous_slowest = previous.inject(nil) {|a,ts| (a) ? ((a.duration > ts.duration) ? a : ts) : ts} @samples_lock.synchronize do if @random_sampling @harvest_count += 1 if (@harvest_count % @sampling_rate) == 0 result << @random_sample if @random_sample else @random_sample = nil # if we don't nil this out, then we won't send the slowest if slowest == @random_sample end end slowest = @slowest_sample @slowest_sample = nil if slowest && slowest != @random_sample && slowest.duration >= slow_threshold if previous_slowest.nil? || previous_slowest.duration < slowest.duration result << slowest else result << previous_slowest end end @random_sample = nil @last_sample = nil end # Truncate the samples at 2100 segments. The UI will clamp them at 2000 segments anyway. # This will save us memory and bandwidth. result.each { |sample| sample.truncate(@segment_limit) } result end |
#ignore_transaction ⇒ Object
116 117 118 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 116 def ignore_transaction builder.ignore_transaction if builder end |
#notice_first_scope_push(time) ⇒ Object
46 47 48 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 46 def notice_first_scope_push(time) start_builder(time) unless disabled end |
#notice_pop_scope(scope, time = Time.now.to_f) ⇒ Object
80 81 82 83 84 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 80 def notice_pop_scope(scope, time = Time.now.to_f) return unless builder raise "frozen already???" if builder.sample.frozen? builder.trace_exit(scope, time) end |
#notice_profile(profile) ⇒ Object
119 120 121 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 119 def notice_profile(profile) builder.set_profile(profile) if builder end |
#notice_push_scope(scope, time = Time.now.to_f) ⇒ Object
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 50 def notice_push_scope(scope, time=Time.now.to_f) return unless builder builder.trace_entry(scope, time) # in developer mode, capture the stack trace with the segment. # this is cpu and memory expensive and therefore should not be # turned on in production mode if NewRelic::Control.instance.developer_mode? segment = builder.current_segment if segment # Strip stack frames off the top that match /new_relic/agent/ trace = caller while trace.first =~/\/lib\/new_relic\/agent\// trace.shift end trace = trace[0..39] if trace.length > 40 segment[:backtrace] = trace end end end |
#notice_scope_empty(time = Time.now.to_f) ⇒ Object
This is called when we are done with the transaction. We’ve unwound the stack to the top level.
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 88 def notice_scope_empty(time=Time.now.to_f) last_builder = builder return unless last_builder last_builder.finish_trace(time) clear_builder return if last_builder.ignored? @samples_lock.synchronize do @last_sample = last_builder.sample @random_sample = @last_sample if @random_sampling # ensure we don't collect more than a specified number of samples in memory @samples << @last_sample if NewRelic::Control.instance.developer_mode? @samples.shift while @samples.length > @max_samples if @slowest_sample.nil? || @slowest_sample.duration < @last_sample.duration @slowest_sample = @last_sample end end end |
#notice_sql(sql, config, duration) ⇒ Object
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 132 def notice_sql(sql, config, duration) return unless builder if Thread::current[:record_sql] != false segment = builder.current_segment if segment current_sql = segment[:sql] sql = current_sql + ";\n" + sql if current_sql if sql.length > (MAX_SQL_LENGTH - 4) sql = sql[0..MAX_SQL_LENGTH-4] + '...' end segment[:sql] = sql segment[:connection_config] = config segment[:backtrace] = caller.join("\n") if duration >= @stack_trace_threshold end end end |
#notice_transaction(path, uri = nil, params = {}) ⇒ Object
112 113 114 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 112 def notice_transaction(path, uri=nil, params={}) builder.set_transaction_info(path, uri, params) if !disabled && builder end |
#notice_transaction_cpu_time(cpu_time) ⇒ Object
123 124 125 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 123 def notice_transaction_cpu_time(cpu_time) builder.set_transaction_cpu_time(cpu_time) if builder end |
#reset! ⇒ Object
reset samples without rebooting the web server
197 198 199 200 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 197 def reset! @samples = [] @last_sample = nil end |
#scope_depth ⇒ Object
74 75 76 77 78 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 74 def scope_depth return 0 unless builder builder.scope_depth end |