Class: ScoutApm::Agent
- Inherits:
-
Object
- Object
- ScoutApm::Agent
- Defined in:
- lib/scout_apm/agent.rb,
lib/scout_apm/agent/logging.rb,
lib/scout_apm/agent/reporting.rb
Overview
The agent gathers performance data from a Ruby application. One Agent instance is created per-Ruby process.
Each Agent object creates a worker thread (unless monitoring is disabled or we’re forking). The worker thread wakes up every Agent#period, merges in-memory metrics w/those saved to disk, saves tshe merged data to disk, and sends it to the Scout server.
Defined Under Namespace
Constant Summary collapse
- @@instance =
see self.instance
nil
Instance Attribute Summary collapse
-
#capacity ⇒ Object
Returns the value of attribute capacity.
-
#config ⇒ Object
Returns the value of attribute config.
-
#layaway ⇒ Object
Returns the value of attribute layaway.
-
#log_file ⇒ Object
path to the log file.
-
#logger ⇒ Object
Returns the value of attribute logger.
-
#metric_lookup ⇒ Object
Hash used to lookup metric ids based on their name and scope.
-
#options ⇒ Object
options passed to the agent when
#start
is called. -
#store ⇒ Object
Accessors below are for associated classes.
Class Method Summary collapse
-
.instance(options = {}) ⇒ Object
All access to the agent is thru this class method to ensure multiple Agent instances are not initialized per-Ruby process.
Instance Method Summary collapse
- #apm_enabled? ⇒ Boolean
-
#app_server_load_hook ⇒ Object
Sends a ping to APM right away, smoothes out onboarding Collects up any relevant info (framework, app server, system time, ruby version, etc).
- #environment ⇒ Object
- #exit_handler_unsupported? ⇒ Boolean
-
#handle_exit ⇒ Object
at_exit, calls Agent#shutdown to wrapup metric reporting.
-
#initialize(options = {}) ⇒ Agent
constructor
Note - this doesn’t start instruments or the worker thread.
-
#load_instruments ⇒ Object
Loads the instrumention logic.
- #preconditions_met? ⇒ Boolean
- #should_load_instruments? ⇒ Boolean
-
#shutdown ⇒ Object
Called via an at_exit handler, it (1) stops the background worker and (2) runs it a final time.
-
#start(options = {}) ⇒ Object
This is called via
ScoutApm::Agent.instance.start
when ScoutApm is required in a Ruby application. -
#start_background_worker ⇒ Object
Creates the worker thread.
-
#start_background_worker? ⇒ Boolean
The worker thread will automatically start UNLESS: * A supported application server isn’t detected (example: running via Rails console) * A supported application server is detected, but it forks.
- #started? ⇒ Boolean
Methods included from Reporting
#add_metric_ids, #process_metrics, #reporter, #run_samplers
Methods included from Logging
#apply_log_format, #default_log_path, #init_logger, #log_file_path, #log_level, #wants_stdout?
Constructor Details
#initialize(options = {}) ⇒ Agent
Note - this doesn’t start instruments or the worker thread. This is handled via #start
as we don’t want to start the worker thread or install instrumentation if (1) disabled for this environment (2) a worker thread shouldn’t be started (when forking).
29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/scout_apm/agent.rb', line 29 def initialize( = {}) @started = false @options ||= @config = ScoutApm::Config.new([:config_path]) @store = ScoutApm::Store.new @layaway = ScoutApm::Layaway.new @metric_lookup = Hash.new @capacity = ScoutApm::Capacity.new end |
Instance Attribute Details
#capacity ⇒ Object
Returns the value of attribute capacity.
15 16 17 |
# File 'lib/scout_apm/agent.rb', line 15 def capacity @capacity end |
#config ⇒ Object
Returns the value of attribute config.
14 15 16 |
# File 'lib/scout_apm/agent.rb', line 14 def config @config end |
#layaway ⇒ Object
Returns the value of attribute layaway.
13 14 15 |
# File 'lib/scout_apm/agent.rb', line 13 def layaway @layaway end |
#log_file ⇒ Object
path to the log file
17 18 19 |
# File 'lib/scout_apm/agent.rb', line 17 def log_file @log_file end |
#logger ⇒ Object
Returns the value of attribute logger.
16 17 18 |
# File 'lib/scout_apm/agent.rb', line 16 def logger @logger end |
#metric_lookup ⇒ Object
Hash used to lookup metric ids based on their name and scope
19 20 21 |
# File 'lib/scout_apm/agent.rb', line 19 def metric_lookup @metric_lookup end |
#options ⇒ Object
options passed to the agent when #start
is called.
18 19 20 |
# File 'lib/scout_apm/agent.rb', line 18 def @options end |
#store ⇒ Object
Accessors below are for associated classes
12 13 14 |
# File 'lib/scout_apm/agent.rb', line 12 def store @store end |
Class Method Details
.instance(options = {}) ⇒ Object
All access to the agent is thru this class method to ensure multiple Agent instances are not initialized per-Ruby process.
22 23 24 |
# File 'lib/scout_apm/agent.rb', line 22 def self.instance( = {}) @@instance ||= self.new() end |
Instance Method Details
#apm_enabled? ⇒ Boolean
45 46 47 |
# File 'lib/scout_apm/agent.rb', line 45 def apm_enabled? config.value('monitor') and !@options[:force] end |
#app_server_load_hook ⇒ Object
Sends a ping to APM right away, smoothes out onboarding Collects up any relevant info (framework, app server, system time, ruby version, etc)
110 111 112 |
# File 'lib/scout_apm/agent.rb', line 110 def app_server_load_hook AppServerLoad.new.run end |
#environment ⇒ Object
41 42 43 |
# File 'lib/scout_apm/agent.rb', line 41 def environment ScoutApm::Environment.instance end |
#exit_handler_unsupported? ⇒ Boolean
114 115 116 |
# File 'lib/scout_apm/agent.rb', line 114 def exit_handler_unsupported? environment.sinatra? || environment.jruby? || environment.rubinius? end |
#handle_exit ⇒ Object
at_exit, calls Agent#shutdown to wrapup metric reporting.
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/scout_apm/agent.rb', line 119 def handle_exit logger.debug "Exit handler not supported" and return if exit_handler_unsupported? at_exit do logger.debug "Shutdown!" # MRI 1.9 bug drops exit codes. # http://bugs.ruby-lang.org/issues/5218 if environment.ruby_19? status = $!.status if $!.is_a?(SystemExit) shutdown exit status if status else shutdown end end end |
#load_instruments ⇒ Object
Loads the instrumention logic.
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/scout_apm/agent.rb', line 175 def load_instruments logger.debug "Installing instrumentation" case environment.framework when :rails require File.(File.join(File.dirname(__FILE__),'instruments/rails/action_controller_instruments.rb')) when :rails3_or_4 require File.(File.join(File.dirname(__FILE__),'instruments/rails3_or_4/action_controller_instruments.rb')) end require File.(File.join(File.dirname(__FILE__),'instruments/active_record_instruments.rb')) require File.(File.join(File.dirname(__FILE__),'instruments/net_http.rb')) require File.(File.join(File.dirname(__FILE__),'instruments/moped_instruments.rb')) require File.(File.join(File.dirname(__FILE__),'instruments/mongoid_instruments.rb')) rescue logger.warn "Exception loading instruments:" logger.warn $!. logger.warn $!.backtrace end |
#preconditions_met? ⇒ Boolean
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/scout_apm/agent.rb', line 49 def preconditions_met? if !apm_enabled? logger.warn "Monitoring isn't enabled for the [#{environment.env}] environment." return false end if !environment.application_name logger.warn "An application name could not be determined. Specify the :name value in scout_apm.yml. Not starting agent." return false end if !environment.app_server_integration.found? logger.warn "Couldn't find a supported app server. Not starting agent." return false end if started? logger.warn "Already started agent." return false end true end |
#should_load_instruments? ⇒ Boolean
170 171 172 |
# File 'lib/scout_apm/agent.rb', line 170 def should_load_instruments? environment.app_server_integration.found? end |
#shutdown ⇒ Object
Called via an at_exit handler, it (1) stops the background worker and (2) runs it a final time. The final run ensures metrics are stored locally to the layaway / reported to scoutapp.com. Otherwise, in-memory metrics would be lost and a gap would appear on restarts.
139 140 141 142 143 |
# File 'lib/scout_apm/agent.rb', line 139 def shutdown return if !started? @background_worker.stop @background_worker.run_once end |
#start(options = {}) ⇒ Object
This is called via ScoutApm::Agent.instance.start
when ScoutApm is required in a Ruby application. It initializes the agent and starts the worker thread (if appropiate).
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/scout_apm/agent.rb', line 75 def start( = {}) @options.merge!() init_logger logger.info "Attempting to start Scout Agent [#{ScoutApm::VERSION}] on [#{environment.hostname}]" return false unless preconditions_met? @started = true logger.info "Starting monitoring for [#{environment.application_name}]. Framework [#{environment.framework}] App Server [#{environment.app_server}]." load_instruments if should_load_instruments? @samplers = [ ScoutApm::Instruments::Process::ProcessCpu.new(environment.processors, logger), ScoutApm::Instruments::Process::ProcessMemory.new(logger) ] app_server_load_hook if start_background_worker? # TODO: Clarify name. This is not the path that unicorn workers take.... # This branch fires only on non-forking servers, directly starts the # background thread and then requests are served. start_background_worker handle_exit logger.info "Scout Agent [#{ScoutApm::VERSION}] Initialized" else # This branch fires on.... master only? of forking servers logger.debug "Not starting worker thread. Will start worker loops after forking." environment.app_server_integration.install end end |
#start_background_worker ⇒ Object
Creates the worker thread. The worker thread is a loop that runs continuously. It sleeps for Agent#period and when it wakes, processes data, either saving it to disk or reporting to Scout.
161 162 163 164 165 166 167 168 |
# File 'lib/scout_apm/agent.rb', line 161 def start_background_worker logger.debug "Creating worker thread." @background_worker = ScoutApm::BackgroundWorker.new @background_worker_thread = Thread.new do @background_worker.start { process_metrics } end # thread new logger.debug "Done creating worker thread." end |
#start_background_worker? ⇒ Boolean
The worker thread will automatically start UNLESS:
-
A supported application server isn’t detected (example: running via Rails console)
-
A supported application server is detected, but it forks. In this case, the agent is started in the forked process.
153 154 155 156 157 |
# File 'lib/scout_apm/agent.rb', line 153 def start_background_worker? return true if environment.app_server == :thin return true if environment.app_server == :webrick return !environment.forking? end |
#started? ⇒ Boolean
145 146 147 |
# File 'lib/scout_apm/agent.rb', line 145 def started? @started end |