# = New Relic Agent # # New Relic RPM is a performance monitoring application for Ruby # applications running in production. For more information on RPM # please visit http://www.newrelic.com. # # The New Relic Agent can be installed in Rails applications to gather # runtime performance metrics, traces, and errors for display in a # Developer Mode UI (mapped to /newrelic in your application server) # or for monitoring and analysis at http://rpm.newrelic.com with just # about any Ruby application. # # For detailed information on configuring or customizing the RPM Agent # please visit our {support and documentation site}[http://support.newrelic.com]. # # == Starting the Agent as a Gem # # For Rails, add: # config.gem 'newrelic_rpm' # to your initialization sequence. # # For merb, do # dependency 'newrelic_rpm' # in the Merb config/init.rb # # For Sinatra, just require the +newrelic_rpm+ gem and it will # automatically detect Sinatra and instrument all the handlers. # # For other frameworks, or to manage the agent manually, # invoke NewRelic::Agent#manual_start directly. # # == Configuring the Agent # # All agent configuration is done in the newrelic.yml file. # This file is by default read from the +config+ directory of the # application root and is subsequently searched for in the application # root directory, and then in a ~/.newrelic directory # # == Using with Rack/Metal # # To instrument middlewares, refer to the docs in # NewRelic::Agent::Instrumentation::Rack. # # == Agent API # # For details on the Agent API, refer to NewRelic::Agent. # # # :main: lib/new_relic/agent.rb module NewRelic # == Agent APIs # This module contains the public API methods for the Agent. # # For adding custom instrumentation to method invocations, refer to # the docs in the class NewRelic::Agent::MethodTracer. # # For information on how to customize the controller # instrumentation, or to instrument something other than Rails so # that high level dispatcher actions or background tasks show up as # first class operations in RPM, refer to # NewRelic::Agent::Instrumentation::ControllerInstrumentation and # NewRelic::Agent::Instrumentation::ControllerInstrumentation::ClassMethods. # # Methods in this module as well as documented methods in # NewRelic::Agent::MethodTracer and # NewRelic::Agent::Instrumentation::ControllerInstrumentation are # available to applications. When the agent is not enabled the # method implementations are stubbed into no-ops to reduce overhead. # # Methods and classes in other parts of the agent are not guaranteed # to be available between releases. # # Refer to the online docs at support.newrelic.com to see how to # access the data collected by custom instrumentation, or e-mail # support at New Relic for help. module Agent extend self require 'new_relic/version' require 'new_relic/local_environment' require 'new_relic/stats' require 'new_relic/delayed_job_injection' require 'new_relic/metrics' require 'new_relic/metric_spec' require 'new_relic/metric_data' require 'new_relic/metric_parser' require 'new_relic/collection_helper' require 'new_relic/transaction_analysis' require 'new_relic/transaction_sample' require 'new_relic/noticed_error' require 'new_relic/histogram' require 'new_relic/agent/chained_call' require 'new_relic/agent/agent' require 'new_relic/agent/shim_agent' require 'new_relic/agent/method_tracer' require 'new_relic/agent/worker_loop' require 'new_relic/agent/stats_engine' require 'new_relic/agent/transaction_sampler' require 'new_relic/agent/error_collector' require 'new_relic/agent/busy_calculator' require 'new_relic/agent/sampler' require 'new_relic/agent/instrumentation/controller_instrumentation' require 'new_relic/agent/samplers/cpu_sampler' require 'new_relic/agent/samplers/memory_sampler' require 'new_relic/agent/samplers/object_sampler' require 'new_relic/agent/samplers/delayed_job_lock_sampler' require 'set' require 'thread' require 'resolv' require 'timeout' # An exception that is thrown by the server if the agent license is invalid. class LicenseException < StandardError; end # An exception that forces an agent to stop reporting until its mongrel is restarted. class ForceDisconnectException < StandardError; end # An exception that forces an agent to restart. class ForceRestartException < StandardError; end # Used to blow out of a periodic task without logging a an error, such as for routine # failures. class ServerConnectionException < StandardError; end # Used for when a transaction trace or error report has too much # data, so we reset the queue to clear the extra-large item class PostTooBigException < ServerConnectionException; end # Reserved for future use. Meant to represent a problem on the server side. class ServerError < StandardError; end class BackgroundLoadingError < StandardError; end @agent = nil # The singleton Agent instance. Used internally. def agent #:nodoc: raise "Plugin not initialized!" if @agent.nil? @agent end def agent= new_instance #:nodoc: @agent = new_instance end alias instance agent #:nodoc: # Get or create a statistics gatherer that will aggregate numerical data # under a metric name. # # +metric_name+ should follow a slash separated path convention. Application # specific metrics should begin with "Custom/". # # Return a NewRelic::Stats that accepts data # via calls to add_data_point(value). def get_stats(metric_name, use_scope=false) @agent.stats_engine.get_stats(metric_name, use_scope) end alias get_stats_no_scope get_stats # Get the logger for the agent. Available after the agent has initialized. # This sends output to the agent log file. def logger NewRelic::Control.instance.log end # Call this to manually start the Agent in situations where the Agent does # not auto-start. # # When the app environment loads, so does the Agent. However, the # Agent will only connect to RPM if a web front-end is found. If # you want to selectively monitor ruby processes that don't use # web plugins, then call this method in your code and the Agent # will fire up and start reporting to RPM. # # Options are passed in as overrides for values in the # newrelic.yml, such as app_name. In addition, the option +log+ # will take a logger that will be used instead of the standard # file logger. The setting for the newrelic.yml section to use # (ie, RAILS_ENV) can be overridden with an :env argument. # def manual_start(options={}) raise unless Hash === options NewRelic::Control.instance.init_plugin({ :agent_enabled => true, :sync_startup => true }.merge(options)) end # Register this method as a callback for processes that fork # jobs. # # If the master/parent connects to the agent prior to forking the # agent in the forked process will use that agent_run. Otherwise # the forked process will establish a new connection with the # server. # # Use this especially when you fork the process to run background # jobs or other work. If you are doing this with a web dispatcher # that forks worker processes then you will need to force the # agent to reconnect, which it won't do by default. Passenger and # Unicorn are already handled, nothing special needed for them. # # Options: # * :force_reconnect => true to force the spawned process to # establish a new connection, such as when forking a long running process. # The default is false--it will only connect to the server if the parent # had not connected. # * :keep_retrying => false if we try to initiate a new # connection, this tells me to only try it once so this method returns # quickly if there is some kind of latency with the server. def after_fork(options={}) agent.after_fork(options) end # Clear out any unsent metric data. def reset_stats agent.reset_stats end # Shutdown the agent. Call this before exiting. Sends any queued data # and kills the background thread. def shutdown agent.shutdown end # Add instrumentation files to the agent. The argument should be # a glob matching ruby scripts which will be executed at the time # instrumentation is loaded. Since instrumentation is not loaded # when the agent is not running it's better to use this method to # register instrumentation than just loading the files directly, # although that probably also works. def add_instrumentation file_pattern NewRelic::Control.instance.add_instrumentation file_pattern end # This method sets the block sent to this method as a sql # obfuscator. The block will be called with a single String SQL # statement to obfuscate. The method must return the obfuscated # String SQL. If chaining of obfuscators is required, use type = # :before or :after # # type = :before, :replace, :after # # Example: # # NewRelic::Agent.set_sql_obfuscator(:replace) do |sql| # my_obfuscator(sql) # end # def set_sql_obfuscator(type = :replace, &block) agent.set_sql_obfuscator type, &block end # This method sets the state of sql recording in the transaction # sampler feature. Within the given block, no sql will be recorded # # usage: # # NewRelic::Agent.disable_sql_recording do # ... # end # def disable_sql_recording state = agent.set_record_sql(false) begin yield ensure agent.set_record_sql(state) end end # This method disables the recording of transaction traces in the given # block. See also #disable_all_tracing def disable_transaction_tracing state = agent.set_record_tt(false) begin yield ensure agent.set_record_tt(state) end end # Cancel the collection of the current transaction in progress, if # any. Only affects the transaction started on this thread once # it has started and before it has completed. def abort_transaction! # The class may not be loaded if the agent is disabled if defined? NewRelic::Agent::Instrumentation::MetricFrame NewRelic::Agent::Instrumentation::MetricFrame.abort_transaction! end end # Yield to the block without collecting any metrics or traces in # any of the subsequent calls. If executed recursively, will keep # track of the first entry point and turn on tracing again after # leaving that block. This uses the thread local # +newrelic_untrace+ def disable_all_tracing agent.push_trace_execution_flag(false) yield ensure agent.pop_trace_execution_flag end # Check to see if we are capturing metrics currently on this thread. def is_execution_traced? Thread.current[:newrelic_untraced].nil? || Thread.current[:newrelic_untraced].last != false end # Set a filter to be applied to errors that RPM will track. The # block should evalute to the exception to track (which could be # different from the original exception) or nil to ignore this # exception. # # The block is yielded to with the exception to filter. # # Return the new block or the existing filter Proc if no block is passed. # def ignore_error_filter(&block) agent.error_collector.ignore_error_filter(&block) end # Record the given error in RPM. It will be passed through the # #ignore_error_filter if there is one. # # * exception is the exception which will be recorded # Options: # * :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 # def notice_error(exception, options={}) NewRelic::Agent::Instrumentation::MetricFrame.notice_error(exception, options) end # Add parameters to the current transaction trace on the call stack. # def add_custom_parameters(params) NewRelic::Agent::Instrumentation::MetricFrame.add_custom_parameters(params) end # The #add_request_parameters method is aliased to #add_custom_parameters # and is now deprecated. alias add_request_parameters add_custom_parameters #:nodoc: # 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. def with_database_metric_name(model, method, &block) if frame = NewRelic::Agent::Instrumentation::MetricFrame.current frame.with_database_metric_name(model, method, &block) else yield end end end end