lib/new_relic/agent/agent.rb in newrelic_rpm-3.6.2.96 vs lib/new_relic/agent/agent.rb in newrelic_rpm-3.6.3.103.beta

- old
+ new

@@ -14,10 +14,11 @@ require 'new_relic/agent/configuration/manager' require 'new_relic/agent/database' require 'new_relic/agent/thread_profiler' require 'new_relic/agent/event_listener' require 'new_relic/agent/cross_app_monitor' +require 'new_relic/agent/request_sampler' require 'new_relic/environment_report' module NewRelic module Agent @@ -38,10 +39,11 @@ @thread_profiler = NewRelic::Agent::ThreadProfiler.new @cross_app_monitor = NewRelic::Agent::CrossAppMonitor.new(@events) @error_collector = NewRelic::Agent::ErrorCollector.new @transaction_rules = NewRelic::Agent::RulesEngine.new @metric_rules = NewRelic::Agent::RulesEngine.new + @request_sampler = NewRelic::Agent::RequestSampler.new(@events) @connect_state = :pending @connect_attempts = 0 @last_harvest_time = Time.now @@ -49,21 +51,10 @@ # FIXME: temporary work around for RUBY-839 if Agent.config[:monitor_mode] @service = NewRelic::Agent::NewRelicService.new end - - txn_tracer_enabler = Proc.new do - if NewRelic::Agent.config[:'transaction_tracer.enabled'] || - NewRelic::Agent.config[:developer_mode] - @stats_engine.transaction_sampler = @transaction_sampler - else - @stats_engine.transaction_sampler = nil - end - end - Agent.config.register_callback(:'transaction_tracer.enabled', &txn_tracer_enabler) - Agent.config.register_callback(:developer_mode, &txn_tracer_enabler) end # contains all the class-level methods for NewRelic::Agent::Agent module ClassMethods # Should only be called by NewRelic::Control - returns a @@ -202,10 +193,12 @@ disconnected? || @worker_thread && @worker_thread.alive? ::NewRelic::Agent.logger.debug "Starting the worker thread in #{$$} after forking." + reset_objects_with_locks + # Clear out stats that are left over from parent process reset_stats # Don't ever check to see if this is a spawner. If we're in a forked process # I'm pretty sure we're not also forking new instances. @@ -322,11 +315,11 @@ # Log startup information that we almost always want to know def log_startup log_environment log_dispatcher - log_app_names + log_app_name end # Log the environment the app thinks it's running in. # Useful in debugging, as this is the key for config YAML lookups. def log_environment @@ -340,18 +333,18 @@ dispatcher_name = Agent.config[:dispatcher].to_s return if log_if(dispatcher_name.empty?, :info, "No known dispatcher detected.") ::NewRelic::Agent.logger.info "Dispatcher: #{dispatcher_name}" end + def log_app_name + ::NewRelic::Agent.logger.info "Application: #{Agent.config.app_names.join(", ")}" + end + # Logs the configured application names - def log_app_names + def app_name_configured? names = Agent.config.app_names - if names.respond_to?(:any?) && names.any? - ::NewRelic::Agent.logger.info "Application: #{names.join(", ")}" - else - ::NewRelic::Agent.logger.error 'Unable to determine application name. Please set the application name in your newrelic.yml or in a NEW_RELIC_APP_NAME environment variable.' - end + return names.respond_to?(:any?) && names.any? end # Connecting in the foreground blocks further startup of the # agent until we have a connection - useful in cases where # you're trying to log a very-short-running process and want @@ -474,19 +467,36 @@ end end include Start - # Logs a bunch of data and starts the agent, if needed - def start - return if already_started? || disabled? + # Check to see if the agent should start, returning +true+ if it should. + def agent_should_start? + return false if already_started? || disabled? + if defer_for_resque? ::NewRelic::Agent.logger.debug "Deferring startup for Resque in case it daemonizes" - return + return false end + unless app_name_configured? + NewRelic::Agent.logger.error "No application name configured.", + "The Agent cannot start without at least one. Please check your ", + "newrelic.yml and ensure that it is valid and has at least one ", + "value set for app_name in the #{NewRelic::Control.instance.env} ", + "environment." + return false + end + + return true + end + + # Logs a bunch of data and starts the agent, if needed + def start + return unless agent_should_start? + @started = true @local_host = determine_host log_startup check_config_and_start_agent log_version_and_pid @@ -501,10 +511,17 @@ @unsent_timeslice_data = {} @last_harvest_time = Time.now @launch_time = Time.now end + # Clear out state for any objects that we know lock from our parents + # This is necessary for cases where we're in a forked child and Ruby + # might be holding locks for background thread that aren't there anymore. + def reset_objects_with_locks + @stats_engine = NewRelic::Agent::StatsEngine.new + end + def add_harvest_sampler(subclass) begin ::NewRelic::Agent.logger.debug "#{subclass.name} not supported on this platform." and return unless subclass.supported_on_this_platform? sampler = subclass.new if subclass.use_harvest_sampler? @@ -1011,10 +1028,21 @@ # 20 instances to prevent leakage @unsent_errors = [] end end + # Fetch samples from the RequestSampler and send them. + def harvest_and_send_analytic_event_data + samples = @request_sampler.samples + @service.analytic_event_data(samples) unless samples.empty? + @request_sampler.reset + rescue => e + NewRelic::Agent.logger.debug "Failed to sent analytics; throttling to conserve memory" + @request_sampler.throttle + raise + end + def check_for_agent_commands commands = @service.get_agent_commands ::NewRelic::Agent.logger.debug "Received get_agent_commands = #{commands.inspect}" @thread_profiler.respond_to_commands(commands) do |command_id, error| @@ -1029,9 +1057,10 @@ @service.session do # use http keep-alive harvest_and_send_errors harvest_and_send_slowest_sample harvest_and_send_slowest_sql harvest_and_send_timeslice_data + harvest_and_send_analytic_event_data harvest_and_send_thread_profile(disconnecting) check_for_agent_commands end rescue EOFError => e