Class: NewRelic::Agent::Instrumentation::MetricFrame
- Inherits:
-
Object
- Object
- NewRelic::Agent::Instrumentation::MetricFrame
- Defined in:
- lib/new_relic/agent/instrumentation/metric_frame.rb
Constant Summary collapse
- @@check_server_connection =
false
- @@java_classes_loaded =
false
Instance Attribute Summary collapse
-
#apdex_start ⇒ Object
Returns the value of attribute apdex_start.
-
#database_metric_name ⇒ Object
Returns the value of attribute database_metric_name.
-
#depth ⇒ Object
readonly
Returns the value of attribute depth.
-
#exception ⇒ Object
Returns the value of attribute exception.
-
#filtered_params ⇒ Object
Returns the value of attribute filtered_params.
-
#force_flag ⇒ Object
Returns the value of attribute force_flag.
-
#jruby_cpu_start ⇒ Object
Returns the value of attribute jruby_cpu_start.
-
#process_cpu_start ⇒ Object
Returns the value of attribute process_cpu_start.
-
#request ⇒ Object
Give the current metric frame a request context.
-
#start ⇒ Object
Returns the value of attribute start.
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.
- .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.
- .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.
-
.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.
Instance Method Summary collapse
-
#abort_transaction! ⇒ Object
Call this to ensure that the current transaction is not saved.
- #add_custom_parameters(p) ⇒ Object
- #category ⇒ Object
- #custom_parameters ⇒ Object
-
#initialize ⇒ MetricFrame
constructor
A new instance of MetricFrame.
- #metric_name ⇒ Object
-
#notice_error(e, options = {}) ⇒ Object
Do not call this.
- #path ⇒ Object
-
#pop ⇒ Object
Unwind one stack level.
-
#push(category, path) ⇒ Object
Indicate that we are entering a measured controller action or task.
- #record_apdex ⇒ Object
-
#recorded_metrics ⇒ Object
Return the array of metrics to record for the current metric frame.
- #recording_web_transaction?(cat = category) ⇒ Boolean
-
#referer ⇒ Object
For the current web transaction, return the full referer, minus the host string, or nil.
-
#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.
-
#with_database_metric_name(model, method) ⇒ Object
Yield to a block that is run with a database metric name context.
Constructor Details
#initialize ⇒ MetricFrame
Returns a new instance of MetricFrame.
61 62 63 64 65 66 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 61 def initialize @start = Time.now.to_f @path_stack = [] # stack of [controller, path] elements @jruby_cpu_start = jruby_cpu_time @process_cpu_start = process_cpu end |
Instance Attribute Details
#apdex_start ⇒ Object
Returns the value of attribute apdex_start.
9 10 11 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 9 def apdex_start @apdex_start end |
#database_metric_name ⇒ Object
Returns the value of attribute database_metric_name.
9 10 11 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 9 def database_metric_name @database_metric_name end |
#depth ⇒ Object (readonly)
Returns the value of attribute depth.
59 60 61 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 59 def depth @depth end |
#exception ⇒ Object
Returns the value of attribute exception.
9 10 11 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 9 def exception @exception end |
#filtered_params ⇒ Object
Returns the value of attribute filtered_params.
9 10 11 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 9 def filtered_params @filtered_params end |
#force_flag ⇒ Object
Returns the value of attribute force_flag.
9 10 11 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 9 def force_flag @force_flag end |
#jruby_cpu_start ⇒ Object
Returns the value of attribute jruby_cpu_start.
9 10 11 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 9 def jruby_cpu_start @jruby_cpu_start end |
#process_cpu_start ⇒ Object
Returns the value of attribute process_cpu_start.
9 10 11 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 9 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.
16 17 18 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 16 def request @request end |
#start ⇒ Object
Returns the value of attribute start.
9 10 11 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 9 def start @start end |
Class Method Details
.abort_transaction! ⇒ Object
Indicate that you don’t want to keep the currently saved transaction information
77 78 79 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 77 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.
179 180 181 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 179 def self.add_custom_parameters(p) current.add_custom_parameters(p) if current end |
.check_server_connection=(value) ⇒ Object
20 21 22 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 20 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.
25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 25 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. NewRelic::Agent.instance.after_fork(:keep_retrying => false) if @@check_server_connection Thread.current[:newrelic_metric_frame] = new end |
.custom_parameters ⇒ Object
183 184 185 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 183 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.
39 40 41 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 39 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
151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 151 def self.notice_error(e, ={}) if request = .delete(:request) [:referer] = referer_from_request(request) [:uri] = uri_from_request(request) end if current current.notice_error(e, ) else NewRelic::Agent.instance.error_collector.notice_error(e, ) end end |
.recording_web_transaction? ⇒ Boolean
245 246 247 248 249 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 245 def self.recording_web_transaction? if c = Thread.current[:newrelic_metric_frame] c.recording_web_transaction? end end |
.referer ⇒ Object
43 44 45 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 43 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.
257 258 259 260 261 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 257 def self.referer_from_request(request) if request && request.respond_to?(:referer) request.referer.to_s.split('?').first end end |
.update_apdex(stat, duration, failed) ⇒ Object
Record an apdex value for the given stat. non-nil ‘failed’ the apdex should be recorded as a failure regardless of duration.
277 278 279 280 281 282 283 284 285 286 287 288 289 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 277 def self.update_apdex(stat, duration, failed) 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.
264 265 266 267 268 269 270 271 272 273 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 264 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 |
Instance Method Details
#abort_transaction! ⇒ Object
Call this to ensure that the current transaction is not saved
92 93 94 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 92 def abort_transaction! NewRelic::Agent.instance.transaction_sampler.ignore_transaction end |
#add_custom_parameters(p) ⇒ Object
241 242 243 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 241 def add_custom_parameters(p) custom_parameters.merge!(p) end |
#category ⇒ Object
105 106 107 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 105 def category @path_stack.last.first end |
#custom_parameters ⇒ Object
237 238 239 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 237 def custom_parameters @custom_parameters ||= {} end |
#metric_name ⇒ Object
196 197 198 199 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 196 def metric_name return nil if @path_stack.empty? category + '/' + path end |
#notice_error(e, options = {}) ⇒ Object
Do not call this. Invoke the class method instead.
164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 164 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 NewRelic::Agent.instance.error_collector.notice_error(e, ) self.exception = e end end |
#path ⇒ Object
109 110 111 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 109 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.
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 115 def pop category, path = @path_stack.pop if category.nil? NewRelic::Agent.logger.error "Underflow in metric frames: #{caller.join("\n ")}" end if @path_stack.empty? if NewRelic::Agent.is_execution_traced? cpu_burn = nil if @process_cpu_start cpu_burn = process_cpu - @process_cpu_start elsif @jruby_cpu_start cpu_burn = jruby_cpu_time - @jruby_cpu_start NewRelic::Agent.get_stats_no_scope(NewRelic::Metrics::USER_TIME).record_data_point(cpu_burn) end NewRelic::Agent.instance.transaction_sampler.notice_transaction_cpu_time(cpu_burn) if cpu_burn NewRelic::Agent.instance.histogram.process(Time.now.to_f - start) if recording_web_transaction?(category) NewRelic::Agent.instance.transaction_sampler.notice_scope_empty end NewRelic::Agent.instance.stats_engine.end_transaction Thread.current[:newrelic_metric_frame] = nil else # path stack not empty # change the transaction name back to whatever was on the stack. NewRelic::Agent.instance.stats_engine.scope_name = metric_name end end |
#push(category, path) ⇒ Object
Indicate that we are entering a measured controller action or task. Make sure you unwind every push with a pop call.
70 71 72 73 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 70 def push(category, path) NewRelic::Agent.instance.transaction_sampler.notice_first_scope_push(start) @path_stack.push [category, path] end |
#record_apdex ⇒ Object
187 188 189 190 191 192 193 194 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 187 def record_apdex return unless recording_web_transaction? && NewRelic::Agent.is_execution_traced? ending = Time.now.to_f summary_stat = NewRelic::Agent.instance.stats_engine.get_custom_stats("Apdex", NewRelic::ApdexStats) controller_stat = NewRelic::Agent.instance.stats_engine.get_custom_stats("Apdex/#{path}", NewRelic::ApdexStats) self.class.update_apdex(summary_stat, ending - apdex_start, exception) self.class.update_apdex(controller_stat, ending - start, exception) end |
#recorded_metrics ⇒ Object
Return the array of metrics to record for the current metric frame.
202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 202 def recorded_metrics metrics = [ metric_name ] if @path_stack.size == 1 if recording_web_transaction? metrics += ["HttpDispatcher"] else metrics += ["#{category}/all", "OtherTransaction/all"] end end metrics end |
#recording_web_transaction?(cat = category) ⇒ Boolean
251 252 253 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 251 def recording_web_transaction?(cat = category) 0 == cat.index("Controller") end |
#referer ⇒ Object
For the current web transaction, return the full referer, minus the host string, or nil.
87 88 89 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 87 def referer @referer ||= self.class.referer_from_request(@request) 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.
97 98 99 100 101 102 103 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 97 def start_transaction NewRelic::Agent.instance.stats_engine.start_transaction metric_name # Only push the transaction context info once, on entry: if @path_stack.size == 1 NewRelic::Agent.instance.transaction_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.
82 83 84 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 82 def uri @uri ||= self.class.uri_from_request(@request) unless @request.nil? 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.
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'lib/new_relic/agent/instrumentation/metric_frame.rb', line 221 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 |