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.
-
.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.
70 71 72 73 74 75 76 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 70 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
21 22 23 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 21 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
24 25 26 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 24 def database_metric_name @database_metric_name end |
#depth ⇒ Object (readonly)
Returns the value of attribute depth.
68 69 70 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 68 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
24 25 26 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 24 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
24 25 26 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 24 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
24 25 26 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 24 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
24 25 26 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 24 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
24 25 26 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 24 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.
31 32 33 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 31 def request @request end |
#start ⇒ Object
A Time instance for the start time, never nil
20 21 22 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 20 def start @start end |
Class Method Details
.abort_transaction! ⇒ Object
Indicate that you don’t want to keep the currently saved transaction information
104 105 106 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 104 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.
194 195 196 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 194 def self.add_custom_parameters(p) current.add_custom_parameters(p) if current end |
.agent ⇒ Object
52 53 54 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 52 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.
36 37 38 39 40 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 36 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
198 199 200 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 198 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.
44 45 46 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 44 def self.database_metric_name current && current.database_metric_name 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
165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 165 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
306 307 308 309 310 311 312 313 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 306 def self.record_apdex(current_metric, action_duration, total_duration, is_error) agent.stats_engine.record_metrics('Apdex') do |stat| update_apdex(stat, total_duration, is_error) end agent.stats_engine.record_metrics(current_metric.apdex_metric_path) do |stat| update_apdex(stat, action_duration, is_error) end end |
.recording_web_transaction? ⇒ Boolean
271 272 273 274 275 276 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 271 def self.recording_web_transaction? c = Thread.current[:newrelic_metric_frame] if c c.recording_web_transaction? end end |
.referer ⇒ Object
48 49 50 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 48 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.
288 289 290 291 292 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 288 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
202 203 204 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 202 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.
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 317 def self.update_apdex(stat, duration, failed) apdex_t = TransactionInfo.get.apdex_t duration = duration.to_f 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 # Apdex min and max values should be initialized to the # current apdex_t stat.min_call_time = apdex_t stat.max_call_time = apdex_t end |
.uri_from_request(request) ⇒ Object
Make a safe attempt to get the URI, without the host and query string.
295 296 297 298 299 300 301 302 303 304 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 295 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
206 207 208 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 206 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
119 120 121 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 119 def abort_transaction! transaction_sampler.ignore_transaction end |
#add_custom_parameters(p) ⇒ Object
263 264 265 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 263 def add_custom_parameters(p) custom_parameters.merge!(p) end |
#current_metric ⇒ Object
134 135 136 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 134 def current_metric @path_stack.last end |
#custom_parameters ⇒ Object
251 252 253 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 251 def custom_parameters @custom_parameters ||= {} end |
#is_web_transaction?(metric) ⇒ Boolean
282 283 284 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 282 def is_web_transaction?(metric) 0 == metric.index("Controller") end |
#metric_name ⇒ Object
216 217 218 219 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 216 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.
179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 179 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
139 140 141 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 139 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.
145 146 147 148 149 150 151 152 153 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 145 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.
96 97 98 99 100 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 96 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
259 260 261 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 259 def queue_time start - apdex_start end |
#record_apdex ⇒ Object
210 211 212 213 214 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 210 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.
222 223 224 225 226 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 222 def recorded_metrics metrics = [ metric_name ] metrics += current_metric.summary_metrics if @path_stack.size == 1 metrics end |
#recording_web_transaction? ⇒ Boolean
278 279 280 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 278 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.
114 115 116 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 114 def referer @referer ||= self.class.referer_from_request(@request) end |
#set_user_attributes(attributes) ⇒ Object
267 268 269 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 267 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.
125 126 127 128 129 130 131 132 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 125 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.
109 110 111 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 109 def uri @uri ||= self.class.uri_from_request(@request) unless @request.nil? end |
#user_attributes ⇒ Object
255 256 257 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 255 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.
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 235 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 |