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
- @@check_server_connection =
false
- @@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
- .check_server_connection=(value) ⇒ 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.
76 77 78 79 80 81 82 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 76 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.
74 75 76 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 74 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
110 111 112 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 110 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.
200 201 202 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 200 def self.add_custom_parameters(p) current.add_custom_parameters(p) if current end |
.agent ⇒ Object
58 59 60 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 58 def self.agent NewRelic::Agent.instance end |
.check_server_connection=(value) ⇒ Object
31 32 33 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 31 def self.check_server_connection=(value) @@check_server_connection = value 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 41 42 43 44 45 46 |
# 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 # Reconnect to the server if necessary. This is only done # for old versions of passenger that don't implement an explicit after_fork # event. agent.after_fork(:keep_retrying => false) if @@check_server_connection Thread.current[:newrelic_metric_frame] = new end |
.custom_parameters ⇒ Object
204 205 206 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 204 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.
50 51 52 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 50 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
171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 171 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
312 313 314 315 316 317 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 312 def self.record_apdex(current_metric, action_duration, total_duration, is_error) summary_stat = agent.stats_engine.get_custom_stats("Apdex", NewRelic::ApdexStats) controller_stat = agent.stats_engine.get_custom_stats(current_metric.apdex_metric_path, NewRelic::ApdexStats) update_apdex(summary_stat, total_duration, is_error) update_apdex(controller_stat, action_duration, is_error) end |
.recording_web_transaction? ⇒ Boolean
277 278 279 280 281 282 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 277 def self.recording_web_transaction? c = Thread.current[:newrelic_metric_frame] if c c.recording_web_transaction? end end |
.referer ⇒ Object
54 55 56 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 54 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.
294 295 296 297 298 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 294 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
208 209 210 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 208 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.
321 322 323 324 325 326 327 328 329 330 331 332 333 334 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 321 def self.update_apdex(stat, duration, failed) duration = duration.to_f apdex_t = NewRelic::Control.instance.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.
301 302 303 304 305 306 307 308 309 310 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 301 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
212 213 214 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 212 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
125 126 127 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 125 def abort_transaction! transaction_sampler.ignore_transaction end |
#add_custom_parameters(p) ⇒ Object
269 270 271 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 269 def add_custom_parameters(p) custom_parameters.merge!(p) end |
#current_metric ⇒ Object
140 141 142 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 140 def current_metric @path_stack.last end |
#custom_parameters ⇒ Object
257 258 259 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 257 def custom_parameters @custom_parameters ||= {} end |
#is_web_transaction?(metric) ⇒ Boolean
288 289 290 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 288 def is_web_transaction?(metric) 0 == metric.index("Controller") end |
#metric_name ⇒ Object
222 223 224 225 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 222 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.
185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 185 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
145 146 147 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 145 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.
151 152 153 154 155 156 157 158 159 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 151 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.
102 103 104 105 106 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 102 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
265 266 267 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 265 def queue_time apdex_start - start end |
#record_apdex ⇒ Object
216 217 218 219 220 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 216 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.
228 229 230 231 232 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 228 def recorded_metrics metrics = [ metric_name ] metrics += current_metric.summary_metrics if @path_stack.size == 1 metrics end |
#recording_web_transaction? ⇒ Boolean
284 285 286 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 284 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.
120 121 122 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 120 def referer @referer ||= self.class.referer_from_request(@request) end |
#set_user_attributes(attributes) ⇒ Object
273 274 275 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 273 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.
131 132 133 134 135 136 137 138 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 131 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.
115 116 117 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 115 def uri @uri ||= self.class.uri_from_request(@request) unless @request.nil? end |
#user_attributes ⇒ Object
261 262 263 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 261 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.
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 241 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 |