Class: 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
-
#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, request = 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
#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 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 36 def disable 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.
153 154 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 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 153 def harvest(previous = nil, slow_threshold = 2.0) 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
114 115 116 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 114 def ignore_transaction builder.ignore_transaction if builder end |
#notice_first_scope_push(time) ⇒ Object
45 46 47 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 45 def notice_first_scope_push(time) start_builder(time) end |
#notice_pop_scope(scope, time = Time.now.to_f) ⇒ Object
79 80 81 82 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 79 def notice_pop_scope(scope, time = Time.now.to_f) return unless builder builder.trace_exit(scope, time) end |
#notice_profile(profile) ⇒ Object
117 118 119 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 117 def notice_profile(profile) builder.set_profile(profile) if builder end |
#notice_push_scope(scope, time = Time.now.to_f) ⇒ Object
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 49 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.
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 86 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
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 130 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, request = nil, params = {}) ⇒ Object
110 111 112 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 110 def notice_transaction(path, request=nil, params={}) builder.set_transaction_info(path, request, params) if start_builder end |
#notice_transaction_cpu_time(cpu_time) ⇒ Object
121 122 123 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 121 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
194 195 196 197 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 194 def reset! @samples = [] @last_sample = nil end |
#scope_depth ⇒ Object
73 74 75 76 77 |
# File 'lib/new_relic/agent/transaction_sampler.rb', line 73 def scope_depth return 0 unless builder builder.scope_depth end |