Class: NewRelic::Agent::Instrumentation::MetricFrame
- Inherits:
-
Object
- Object
- NewRelic::Agent::Instrumentation::MetricFrame
- Includes:
- Pop
- Defined in:
- lib/new_relic/agent/instrumentation/metric_frame.rb,
lib/new_relic/agent/instrumentation/metric_frame/pop.rb
Defined Under Namespace
Modules: Pop
Constant Summary collapse
- @@java_classes_loaded =
false
Instance Attribute Summary collapse
-
#apdex_start ⇒ Object
A Time instance used for calculating the apdex score, which.
-
#database_metric_name ⇒ Object
might end up being @start, or it might be further upstream if we can find a request header for the queue entry time.
-
#depth ⇒ Object
readonly
Returns the value of attribute depth.
-
#exception ⇒ Object
might end up being @start, or it might be further upstream if we can find a request header for the queue entry time.
-
#filtered_params ⇒ Object
might end up being @start, or it might be further upstream if we can find a request header for the queue entry time.
-
#force_flag ⇒ Object
might end up being @start, or it might be further upstream if we can find a request header for the queue entry time.
-
#jruby_cpu_start ⇒ Object
might end up being @start, or it might be further upstream if we can find a request header for the queue entry time.
-
#process_cpu_start ⇒ Object
might end up being @start, or it might be further upstream if we can find a request header for the queue entry time.
-
#request ⇒ Object
Give the current metric frame a request context.
-
#start ⇒ Object
A Time instance for the start time, never nil.
Class Method Summary collapse
-
.abort_transaction! ⇒ Object
Indicate that you don’t want to keep the currently saved transaction information.
-
.add_custom_parameters(p) ⇒ Object
Add context parameters to the metric frame.
- .agent ⇒ Object
-
.current(create_if_empty = nil) ⇒ Object
Return the currently active metric frame, or nil.
- .custom_parameters ⇒ Object
-
.database_metric_name ⇒ Object
This is the name of the model currently assigned to database measurements, overriding the default.
-
.initialize_apdex(metric_name) ⇒ Object
Apdex min and max values should be initialized to the current apdex_t.
-
.notice_error(e, options = {}) ⇒ Object
If we have an active metric frame, notice the error and increment the error metric.
- .record_apdex(current_metric, action_duration, total_duration, is_error) ⇒ Object
- .recording_web_transaction? ⇒ Boolean
- .referer ⇒ Object
-
.referer_from_request(request) ⇒ Object
Make a safe attempt to get the referer from a request object, generally successful when it’s a Rack request.
- .set_user_attributes(attributes) ⇒ Object
-
.update_apdex(stat, duration, failed) ⇒ Object
Record an apdex value for the given stat.
-
.uri_from_request(request) ⇒ Object
Make a safe attempt to get the URI, without the host and query string.
- .user_attributes ⇒ Object
Instance Method Summary collapse
-
#abort_transaction! ⇒ Object
Call this to ensure that the current transaction is not saved.
- #add_custom_parameters(p) ⇒ Object
- #current_metric ⇒ Object
- #custom_parameters ⇒ Object
-
#initialize ⇒ MetricFrame
constructor
A new instance of MetricFrame.
- #is_web_transaction?(metric) ⇒ Boolean
- #metric_name ⇒ Object
-
#notice_error(e, options = {}) ⇒ Object
Do not call this.
-
#path ⇒ Object
Return the path, the part of the metric after the category.
-
#pop ⇒ Object
Unwind one stack level.
-
#push(m) ⇒ Object
Indicate that we are entering a measured controller action or task.
- #queue_time ⇒ Object
- #record_apdex ⇒ Object
-
#recorded_metrics ⇒ Object
Return the array of metrics to record for the current metric frame.
- #recording_web_transaction? ⇒ Boolean
-
#referer ⇒ Object
For the current web transaction, return the full referer, minus the host string, or nil.
- #set_user_attributes(attributes) ⇒ Object
-
#start_transaction ⇒ Object
This needs to be called after entering the call to trace the controller action, otherwise the controller action blames itself.
-
#uri ⇒ Object
For the current web transaction, return the path of the URI minus the host part and query string, or nil.
- #user_attributes ⇒ Object
-
#with_database_metric_name(model, method) ⇒ Object
Yield to a block that is run with a database metric name context.
Methods included from Pop
#clear_thread_metric_frame!, #cpu_burn, #current_stack_metric, #end_transaction!, #handle_empty_path_stack, #jruby_cpu_burn, #log_underflow, #normal_cpu_burn, #notice_scope_empty, #notify_transaction_sampler, #record_jruby_cpu_burn, #record_transaction_cpu, #set_new_scope!, #traced?
Constructor Details
#initialize ⇒ MetricFrame
Returns a new instance of MetricFrame.
66 67 68 69 70 71 72 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 66 def initialize @start = Time.now @path_stack = [] # stack of [controller, path] elements @jruby_cpu_start = jruby_cpu_time @process_cpu_start = process_cpu Thread.current[:last_metric_frame] = self end |
Instance Attribute Details
#apdex_start ⇒ Object
A Time instance used for calculating the apdex score, which
17 18 19 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 17 def apdex_start @apdex_start end |
#database_metric_name ⇒ Object
might end up being @start, or it might be further upstream if we can find a request header for the queue entry time
20 21 22 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 20 def database_metric_name @database_metric_name end |
#depth ⇒ Object (readonly)
Returns the value of attribute depth.
64 65 66 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 64 def depth @depth end |
#exception ⇒ Object
might end up being @start, or it might be further upstream if we can find a request header for the queue entry time
20 21 22 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 20 def exception @exception end |
#filtered_params ⇒ Object
might end up being @start, or it might be further upstream if we can find a request header for the queue entry time
20 21 22 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 20 def filtered_params @filtered_params end |
#force_flag ⇒ Object
might end up being @start, or it might be further upstream if we can find a request header for the queue entry time
20 21 22 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 20 def force_flag @force_flag end |
#jruby_cpu_start ⇒ Object
might end up being @start, or it might be further upstream if we can find a request header for the queue entry time
20 21 22 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 20 def jruby_cpu_start @jruby_cpu_start end |
#process_cpu_start ⇒ Object
might end up being @start, or it might be further upstream if we can find a request header for the queue entry time
20 21 22 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 20 def process_cpu_start @process_cpu_start end |
#request ⇒ Object
Give the current metric frame a request context. Use this to get the URI and referer. The request is interpreted loosely as a Rack::Request or an ActionController::AbstractRequest.
27 28 29 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 27 def request @request end |
#start ⇒ Object
A Time instance for the start time, never nil
16 17 18 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 16 def start @start end |
Class Method Details
.abort_transaction! ⇒ Object
Indicate that you don’t want to keep the currently saved transaction information
100 101 102 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 100 def self.abort_transaction! current.abort_transaction! if current end |
.add_custom_parameters(p) ⇒ Object
Add context parameters to the metric frame. This information will be passed in to errors and transaction traces. Keys and Values should be strings, numbers or date/times.
190 191 192 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 190 def self.add_custom_parameters(p) current.add_custom_parameters(p) if current end |
.agent ⇒ Object
48 49 50 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 48 def self.agent NewRelic::Agent.instance end |
.current(create_if_empty = nil) ⇒ Object
Return the currently active metric frame, or nil. Call with true
to create a new metric frame if one is not already on the thread.
32 33 34 35 36 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 32 def self.current(create_if_empty=nil) f = Thread.current[:newrelic_metric_frame] return f if f || !create_if_empty Thread.current[:newrelic_metric_frame] = new end |
.custom_parameters ⇒ Object
194 195 196 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 194 def self.custom_parameters (current && current.custom_parameters) ? current.custom_parameters : {} end |
.database_metric_name ⇒ Object
This is the name of the model currently assigned to database measurements, overriding the default.
40 41 42 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 40 def self.database_metric_name current && current.database_metric_name end |
.initialize_apdex(metric_name) ⇒ Object
Apdex min and max values should be initialized to the current apdex_t
314 315 316 317 318 319 320 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 314 def self.initialize_apdex(metric_name) stats = agent.stats_engine.get_stats_no_scope(metric_name) apdex_t = TransactionInfo.get.apdex_t stats.min_call_time = apdex_t stats.max_call_time = apdex_t return stats end |
.notice_error(e, options = {}) ⇒ Object
If we have an active metric frame, notice the error and increment the error metric. Options:
-
:request
=> Request object to get the uri and referer -
:uri
=> The request path, minus any request params or query string. -
:referer
=> The URI of the referer -
:metric
=> The metric name associated with the transaction -
:request_params
=> Request parameters, already filtered if necessary -
:custom_params
=> Custom parameters
Anything left over is treated as custom params
161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 161 def self.notice_error(e, ={}) request = .delete(:request) if request [:referer] = referer_from_request(request) [:uri] = uri_from_request(request) end if current current.notice_error(e, ) else agent.error_collector.notice_error(e, ) end end |
.record_apdex(current_metric, action_duration, total_duration, is_error) ⇒ Object
302 303 304 305 306 307 308 309 310 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 302 def self.record_apdex(current_metric, action_duration, total_duration, is_error) summary_stat = agent.stats_engine.lookup_stats("Apdex") || initialize_apdex("Apdex") update_apdex(summary_stat, total_duration, is_error) controller_stat = agent.stats_engine.lookup_stats(current_metric.apdex_metric_path) || initialize_apdex(current_metric.apdex_metric_path) update_apdex(controller_stat, action_duration, is_error) end |
.recording_web_transaction? ⇒ Boolean
267 268 269 270 271 272 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 267 def self.recording_web_transaction? c = Thread.current[:newrelic_metric_frame] if c c.recording_web_transaction? end end |
.referer ⇒ Object
44 45 46 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 44 def self.referer current && current.referer end |
.referer_from_request(request) ⇒ Object
Make a safe attempt to get the referer from a request object, generally successful when it’s a Rack request.
284 285 286 287 288 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 284 def self.referer_from_request(request) if request && request.respond_to?(:referer) request.referer.to_s.split('?').first end end |
.set_user_attributes(attributes) ⇒ Object
198 199 200 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 198 def self.set_user_attributes(attributes) current.set_user_attributes(attributes) if current end |
.update_apdex(stat, duration, failed) ⇒ Object
Record an apdex value for the given stat. when ‘failed` the apdex should be recorded as a failure regardless of duration.
324 325 326 327 328 329 330 331 332 333 334 335 336 337 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 324 def self.update_apdex(stat, duration, failed) duration = duration.to_f apdex_t = TransactionInfo.get.apdex_t case when failed stat.record_apdex_f when duration <= apdex_t stat.record_apdex_s when duration <= 4 * apdex_t stat.record_apdex_t else stat.record_apdex_f end end |
.uri_from_request(request) ⇒ Object
Make a safe attempt to get the URI, without the host and query string.
291 292 293 294 295 296 297 298 299 300 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 291 def self.uri_from_request(request) approximate_uri = case when request.respond_to?(:fullpath) then request.fullpath when request.respond_to?(:path) then request.path when request.respond_to?(:request_uri) then request.request_uri when request.respond_to?(:uri) then request.uri when request.respond_to?(:url) then request.url end return approximate_uri[%r{^(https?://.*?)?(/[^?]*)}, 2] || '/' if approximate_uri # ' end |
.user_attributes ⇒ Object
202 203 204 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 202 def self.user_attributes (current) ? current.user_attributes : {} end |
Instance Method Details
#abort_transaction! ⇒ Object
Call this to ensure that the current transaction is not saved
115 116 117 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 115 def abort_transaction! transaction_sampler.ignore_transaction end |
#add_custom_parameters(p) ⇒ Object
259 260 261 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 259 def add_custom_parameters(p) custom_parameters.merge!(p) end |
#current_metric ⇒ Object
130 131 132 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 130 def current_metric @path_stack.last end |
#custom_parameters ⇒ Object
247 248 249 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 247 def custom_parameters @custom_parameters ||= {} end |
#is_web_transaction?(metric) ⇒ Boolean
278 279 280 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 278 def is_web_transaction?(metric) 0 == metric.index("Controller") end |
#metric_name ⇒ Object
212 213 214 215 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 212 def metric_name return nil if @path_stack.empty? current_metric.name end |
#notice_error(e, options = {}) ⇒ Object
Do not call this. Invoke the class method instead.
175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 175 def notice_error(e, ={}) # :nodoc: params = custom_parameters [:referer] = referer if referer [:request_params] = filtered_params if filtered_params [:uri] = uri if uri [:metric] = metric_name .merge!(custom_parameters) if exception != e result = agent.error_collector.notice_error(e, ) self.exception = result if result end end |
#path ⇒ Object
Return the path, the part of the metric after the category
135 136 137 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 135 def path @path_stack.last.last end |
#pop ⇒ Object
Unwind one stack level. It knows if it’s back at the outermost caller and does the appropriate wrapup of the context.
141 142 143 144 145 146 147 148 149 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 141 def pop metric = @path_stack.pop log_underflow if metric.nil? if @path_stack.empty? handle_empty_path_stack(metric) else set_new_scope!(current_stack_metric) end end |
#push(m) ⇒ Object
Indicate that we are entering a measured controller action or task. Make sure you unwind every push with a pop call.
92 93 94 95 96 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 92 def push(m) transaction_sampler.notice_first_scope_push(start) sql_sampler.notice_first_scope_push(start) @path_stack.push NewRelic::MetricParser::MetricParser.for_metric_named(m) end |
#queue_time ⇒ Object
255 256 257 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 255 def queue_time start - apdex_start end |
#record_apdex ⇒ Object
206 207 208 209 210 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 206 def record_apdex() return unless recording_web_transaction? && NewRelic::Agent.is_execution_traced? t = Time.now self.class.record_apdex(current_metric, t - start, t - apdex_start, !exception.nil?) end |
#recorded_metrics ⇒ Object
Return the array of metrics to record for the current metric frame.
218 219 220 221 222 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 218 def recorded_metrics metrics = [ metric_name ] metrics += current_metric.summary_metrics if @path_stack.size == 1 metrics end |
#recording_web_transaction? ⇒ Boolean
274 275 276 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 274 def recording_web_transaction? current_metric && current_metric.is_web_transaction? end |
#referer ⇒ Object
For the current web transaction, return the full referer, minus the host string, or nil.
110 111 112 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 110 def referer @referer ||= self.class.referer_from_request(@request) end |
#set_user_attributes(attributes) ⇒ Object
263 264 265 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 263 def set_user_attributes(attributes) user_attributes.merge!(attributes) end |
#start_transaction ⇒ Object
This needs to be called after entering the call to trace the controller action, otherwise the controller action blames itself. It gets reset in the normal #pop call.
121 122 123 124 125 126 127 128 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 121 def start_transaction agent.stats_engine.start_transaction metric_name # Only push the transaction context info once, on entry: if @path_stack.size == 1 transaction_sampler.notice_transaction(metric_name, uri, filtered_params) sql_sampler.notice_transaction(metric_name, uri, filtered_params) end end |
#uri ⇒ Object
For the current web transaction, return the path of the URI minus the host part and query string, or nil.
105 106 107 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 105 def uri @uri ||= self.class.uri_from_request(@request) unless @request.nil? end |
#user_attributes ⇒ Object
251 252 253 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 251 def user_attributes @user_atrributes ||= {} end |
#with_database_metric_name(model, method) ⇒ Object
Yield to a block that is run with a database metric name context. This means the Database instrumentation will use this for the metric name if it does not otherwise know about a model. This is re-entrant.
-
model
is the DB model class -
method
is the name of the finder method or other method to identify the operation with.
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 231 def with_database_metric_name(model, method) previous = @database_metric_name model_name = case model when Class model.name when String model else model.to_s end @database_metric_name = "ActiveRecord/#{model_name}/#{method}" yield ensure @database_metric_name=previous end |