Module: NewRelic::Agent::Instrumentation::ControllerInstrumentation::ClassMethods
- Defined in:
- lib/new_relic/agent/instrumentation/controller_instrumentation.rb
Instance Method Summary collapse
-
#add_transaction_tracer(method, options = {}) ⇒ Object
Add transaction tracing to the given method.
- #already_added_transaction_tracer?(target, with_method_name) ⇒ Boolean
- #build_method_names(traced_method, punctuation) ⇒ Object
- #generate_argument_list(options) ⇒ Object
-
#newrelic_ignore(specifiers = {}) ⇒ Object
Have NewRelic ignore actions in this controller.
-
#newrelic_ignore_apdex(specifiers = {}) ⇒ Object
Have NewRelic omit apdex measurements on the given actions.
-
#newrelic_ignore_aspect(property, specifiers = {}) ⇒ Object
:nodoc:.
- #newrelic_ignore_enduser(specifiers = {}) ⇒ Object
-
#newrelic_read_attr(attr_name) ⇒ Object
:nodoc:.
-
#newrelic_write_attr(attr_name, value) ⇒ Object
Should be monkey patched into the controller class implemented with the inheritable attribute mechanism.
- #parse_punctuation(method) ⇒ Object
Instance Method Details
#add_transaction_tracer(method, options = {}) ⇒ Object
Add transaction tracing to the given method. This will treat the given method as a main entrypoint for instrumentation, just like controller actions are treated by default. Useful especially for background tasks.
Example for background job:
class Job
include NewRelic::Agent::Instrumentation::ControllerInstrumentation
def run(task)
...
end
# Instrument run so tasks show up under task.name. Note single
# quoting to defer eval to runtime.
add_transaction_tracer :run, :name => '#{args[0].name}'
end
Here’s an example of a controller that uses a dispatcher action to invoke operations which you want treated as top level actions, so they aren’t all lumped into the invoker action.
MyController < ActionController::Base
include NewRelic::Agent::Instrumentation::ControllerInstrumentation
# dispatch the given op to the method given by the service parameter.
def invoke_operation
op = params['operation']
send op
end
# Ignore the invoker to avoid double counting
newrelic_ignore :only => 'invoke_operation'
# Instrument the operations:
add_transaction_tracer :print
add_transaction_tracer :show
add_transaction_tracer :forward
end
Here’s an example of how to pass contextual information into the transaction so it will appear in transaction traces:
class Job
include NewRelic::Agent::Instrumentation::ControllerInstrumentation
def process(account)
...
end
# Include the account name in the transaction details. Note the single
# quotes to defer eval until call time.
add_transaction_tracer :process, :params => '{ :account_name => args[0].name }'
end
See NewRelic::Agent::Instrumentation::ControllerInstrumentation#perform_action_with_newrelic_trace for the full list of available options.
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 192 193 194 195 196 197 |
# File 'lib/new_relic/agent/instrumentation/controller_instrumentation.rb', line 164 def add_transaction_tracer(method, = {}) NewRelic::Agent.record_api_supportability_metric(:add_transaction_tracer) traced_method, punctuation = parse_punctuation(method) with_method_name, without_method_name = build_method_names(traced_method, punctuation) if already_added_transaction_tracer?(self, with_method_name) ::NewRelic::Agent.logger.warn("Transaction tracer already in place for class = #{self.name}, method = #{method.to_s}, skipping") return end # The metric path: [:name] ||= method.to_s code_info = NewRelic::Agent::MethodTracerHelpers.code_information(self, method) argument_list = generate_argument_list(.merge(code_info)) class_eval(<<~EOC) def #{with_method_name}(*args, &block) perform_action_with_newrelic_trace(#{argument_list.join(',')}) do #{without_method_name}(*args, &block) end end ruby2_keywords(:#{with_method_name}) if respond_to?(:ruby2_keywords, true) EOC visibility = NewRelic::Helper.instance_method_visibility(self, method) alias_method(without_method_name, method.to_s) alias_method(method.to_s, with_method_name) send(visibility, method) send(visibility, with_method_name) ::NewRelic::Agent.logger.debug("Traced transaction: class = #{self.name}, method = #{method.to_s}, options = #{.inspect}") end |
#already_added_transaction_tracer?(target, with_method_name) ⇒ Boolean
222 223 224 |
# File 'lib/new_relic/agent/instrumentation/controller_instrumentation.rb', line 222 def already_added_transaction_tracer?(target, with_method_name) NewRelic::Helper.instance_methods_include?(target, with_method_name) end |
#build_method_names(traced_method, punctuation) ⇒ Object
217 218 219 220 |
# File 'lib/new_relic/agent/instrumentation/controller_instrumentation.rb', line 217 def build_method_names(traced_method, punctuation) ["#{traced_method.to_s}_with_newrelic_transaction_trace#{punctuation}", "#{traced_method.to_s}_without_newrelic_transaction_trace#{punctuation}"] end |
#generate_argument_list(options) ⇒ Object
203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/new_relic/agent/instrumentation/controller_instrumentation.rb', line 203 def generate_argument_list() .map do |key, value| value = if value.is_a?(Symbol) value.inspect elsif key == :params value.to_s else %Q("#{value.to_s}") end %Q(:#{key} => #{value}) end end |
#newrelic_ignore(specifiers = {}) ⇒ Object
Have NewRelic ignore actions in this controller. Specify the actions as hash options using :except and :only. If no actions are specified, all actions are ignored.
59 60 61 62 |
# File 'lib/new_relic/agent/instrumentation/controller_instrumentation.rb', line 59 def newrelic_ignore(specifiers = {}) NewRelic::Agent.record_api_supportability_metric(:newrelic_ignore) newrelic_ignore_aspect(NR_DO_NOT_TRACE_KEY, specifiers) end |
#newrelic_ignore_apdex(specifiers = {}) ⇒ Object
Have NewRelic omit apdex measurements on the given actions. Typically used for actions that are not user facing or that skew your overall apdex measurement. Accepts :except and :only options, as with #newrelic_ignore.
70 71 72 73 |
# File 'lib/new_relic/agent/instrumentation/controller_instrumentation.rb', line 70 def newrelic_ignore_apdex(specifiers = {}) NewRelic::Agent.record_api_supportability_metric(:newrelic_ignore_apdex) newrelic_ignore_aspect(NR_IGNORE_APDEX_KEY, specifiers) end |
#newrelic_ignore_aspect(property, specifiers = {}) ⇒ Object
:nodoc:
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/new_relic/agent/instrumentation/controller_instrumentation.rb', line 81 def newrelic_ignore_aspect(property, specifiers = {}) # :nodoc: if specifiers.empty? self.newrelic_write_attr(property, true) elsif !(Hash === specifiers) ::NewRelic::Agent.logger.error("newrelic_#{property} takes an optional hash with :only and :except lists of actions (illegal argument type '#{specifiers.class}')") else # symbolize the incoming values specifiers = specifiers.inject({}) do |memo, (key, values)| if values.is_a?(Array) memo[key] = values.map(&:to_sym) else memo[key] = values.to_sym end memo end self.newrelic_write_attr(property, specifiers) end end |
#newrelic_ignore_enduser(specifiers = {}) ⇒ Object
76 77 78 79 |
# File 'lib/new_relic/agent/instrumentation/controller_instrumentation.rb', line 76 def newrelic_ignore_enduser(specifiers = {}) NewRelic::Agent.record_api_supportability_metric(:newrelic_ignore_enduser) newrelic_ignore_aspect(NR_IGNORE_ENDUSER_KEY, specifiers) end |
#newrelic_read_attr(attr_name) ⇒ Object
:nodoc:
106 107 108 |
# File 'lib/new_relic/agent/instrumentation/controller_instrumentation.rb', line 106 def newrelic_read_attr(attr_name) # :nodoc: instance_variable_get(attr_name) if instance_variable_defined?(attr_name) end |
#newrelic_write_attr(attr_name, value) ⇒ Object
Should be monkey patched into the controller class implemented with the inheritable attribute mechanism.
102 103 104 |
# File 'lib/new_relic/agent/instrumentation/controller_instrumentation.rb', line 102 def newrelic_write_attr(attr_name, value) # :nodoc: instance_variable_set(attr_name, value) end |
#parse_punctuation(method) ⇒ Object
199 200 201 |
# File 'lib/new_relic/agent/instrumentation/controller_instrumentation.rb', line 199 def parse_punctuation(method) [method.to_s.sub(/([?!=])$/, ''), $1] end |