module NewRelic::Agent::Agent::InstanceMethods::Start
Herein lies the corpse of the former 'start' method. May its unmatched flog score rest in pieces.
Public Instance Methods
Check whether we have already started, which is an error condition
# File lib/new_relic/agent/agent.rb, line 288 def already_started? if started? ::NewRelic::Agent.logger.error("Agent Started Already!") true end end
Logs the configured application names
# File lib/new_relic/agent/agent.rb, line 341 def app_name_configured? names = Agent.config.app_names return names.respond_to?(:any?) && names.any? end
Sanity-check the agent configuration and start the agent, setting up the worker thread and the exit handler to shut down the agent
# File lib/new_relic/agent/agent.rb, line 480 def check_config_and_start_agent return unless monitoring? && has_correct_license_key? return if using_forking_dispatcher? setup_and_start_agent 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 to get statistics from before a server connection (typically 20 seconds) exists
# File lib/new_relic/agent/agent.rb, line 351 def connect_in_foreground NewRelic::Agent.disable_all_tracing { connect(:keep_retrying => false) } end
A license key is an arbitrary 40 character string, usually looks something like a SHA1 hash
# File lib/new_relic/agent/agent.rb, line 441 def correct_license_length key = Agent.config[:license_key] if key.length == 40 true else ::NewRelic::Agent.logger.error("Invalid license key: #{key}") false end end
Return true if we're using resque and it hasn't had a chance to (potentially) daemonize itself. This avoids hanging when there's a Thread started before Resque calls Process.daemon (Jira RUBY-857)
# File lib/new_relic/agent/agent.rb, line 467 def defer_for_resque? NewRelic::Agent.config[:dispatcher] == :resque && NewRelic::LanguageSupport.can_fork? && !NewRelic::Agent::PipeChannelManager.listener.started? end
The agent is disabled when it is not force enabled by the 'agent_enabled' option (e.g. in a manual start), or enabled normally through the configuration file
# File lib/new_relic/agent/agent.rb, line 298 def disabled? !Agent.config[:agent_enabled] end
A correct license key exists and is of the proper length
# File lib/new_relic/agent/agent.rb, line 435 def has_correct_license_key? has_license_key? && correct_license_length end
Tell the user when the license key is missing so they can fix it by adding it to the file
# File lib/new_relic/agent/agent.rb, line 424 def has_license_key? if Agent.config[:license_key] && Agent.config[:license_key].length > 0 true else ::NewRelic::Agent.logger.warn("No license key found. " + "This often means your newrelic.yml file was not found, or it lacks a section for the running environment, '#{NewRelic::Control.instance.env}'. You may also want to try linting your newrelic.yml to ensure it is valid YML.") false end end
# File lib/new_relic/agent/agent.rb, line 473 def in_resque_child_process? @service.is_a?(NewRelic::Agent::PipeService) end
# File lib/new_relic/agent/agent.rb, line 390 def install_exit_handler return unless should_install_exit_handler? NewRelic::Agent.logger.debug("Installing at_exit handler") at_exit do if need_exit_code_workaround? exit_status = $!.status if $!.is_a?(SystemExit) shutdown exit exit_status if exit_status else shutdown end end end
# File lib/new_relic/agent/agent.rb, line 328 def log_app_name ::NewRelic::Agent.logger.info "Application: #{Agent.config.app_names.join(", ")}" end
Logs the dispatcher to the log file to assist with debugging. When no debugger is present, logs this fact to assist with proper dispatcher detection
# File lib/new_relic/agent/agent.rb, line 318 def log_dispatcher dispatcher_name = Agent.config[:dispatcher].to_s if dispatcher_name.empty? ::NewRelic::Agent.logger.info 'No known dispatcher detected.' else ::NewRelic::Agent.logger.info "Dispatcher: #{dispatcher_name}" end end
Log the environment the app thinks it's running in. Useful in debugging, as this is the key for config YAML lookups.
# File lib/new_relic/agent/agent.rb, line 311 def log_environment ::NewRelic::Agent.logger.info "Environment: #{NewRelic::Control.instance.env}" end
# File lib/new_relic/agent/agent.rb, line 332 def log_ignore_url_regexes regexes = NewRelic::Agent.config[:'rules.ignore_url_regexes'] unless regexes.empty? ::NewRelic::Agent.logger.info "Ignoring URLs that match the following regexes: #{regexes.map(&:inspect).join(", ")}." end end
Log startup information that we almost always want to know
# File lib/new_relic/agent/agent.rb, line 303 def log_startup log_environment log_dispatcher log_app_name end
Classy logging of the agent version and the current pid, so we can disambiguate processes in the log file and make sure they're running a reasonable version
# File lib/new_relic/agent/agent.rb, line 407 def log_version_and_pid ::NewRelic::Agent.logger.debug "New Relic Ruby Agent #{NewRelic::VERSION::STRING} Initialized: pid = #{$$}" end
Warn the user if they have configured their agent not to send data, that way we can see this clearly in the log file
# File lib/new_relic/agent/agent.rb, line 413 def monitoring? if Agent.config[:monitor_mode] true else ::NewRelic::Agent.logger.warn('Agent configured not to send data in this environment.') false end end
There's an MRI 1.9 bug that loses exit codes in at_exit blocks. A workaround is necessary to get correct exit codes for the agent's test suites. bugs.ruby-lang.org/issues/5218
# File lib/new_relic/agent/agent.rb, line 386 def need_exit_code_workaround? defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby" && RUBY_VERSION.match(/^1\.9/) end
This is the shared method between the main agent startup and the after_fork call restarting the thread in deferred dispatchers.
Treatment of @started and env report is important to get right.
# File lib/new_relic/agent/agent.rb, line 490 def setup_and_start_agent(options={}) @started = true @harvester.mark_started unless in_resque_child_process? generate_environment_report install_exit_handler @harvest_samplers.load_samplers unless Agent.config[:disable_samplers] end connect_in_foreground if Agent.config[:sync_startup] start_worker_thread(options) end
# File lib/new_relic/agent/agent.rb, line 374 def should_install_exit_handler? ( Agent.config[:send_data_on_exit] && !NewRelic::LanguageSupport.using_engine?('jruby') && !sinatra_classic_app? ) end
This matters when the following three criteria are met:
-
A Sinatra 'classic' application is being run
-
The app is being run by executing the main file directly, rather than via a config.ru file.
-
newrelic_rpm is required after sinatra
In this case, the entire application runs from an at_exit handler in Sinatra, and if we were to install ours, it would be executed before the one in Sinatra, meaning that we'd shutdown the agent too early and never collect any data.
# File lib/new_relic/agent/agent.rb, line 366 def sinatra_classic_app? ( defined?(Sinatra::Application) && Sinatra::Application.respond_to?(:run) && Sinatra::Application.run? ) end
If we're using a dispatcher that forks before serving requests, we need to wait until the children are forked before connecting, otherwise the parent process sends useless data
# File lib/new_relic/agent/agent.rb, line 455 def using_forking_dispatcher? if [:puma, :passenger, :rainbows, :unicorn].include? Agent.config[:dispatcher] ::NewRelic::Agent.logger.info "Deferring startup of agent reporting thread because #{Agent.config[:dispatcher]} may fork." true else false end end