Class: ScoutApm::Agent
- Inherits:
-
Object
- Object
- ScoutApm::Agent
- Defined in:
- lib/scout_apm/agent.rb,
lib/scout_apm/agent/exit_handler.rb,
lib/scout_apm/agent/preconditions.rb
Overview
The entry-point for the ScoutApm Agent.
Only one Agent instance is created per-Ruby process, and it coordinates the lifecycle of the monitoring.
- initializes various data stores
- coordinates configuration & logging
- starts background threads, running periodically
- installs shutdown hooks
Defined Under Namespace
Classes: ExitHandler, Preconditions
Constant Summary collapse
- ERROR_SEND_FREQUENCY =
seconds to batch error reports
5
- @@instance =
see self.instance
nil
Instance Attribute Summary collapse
-
#context ⇒ Object
readonly
Returns the value of attribute context.
-
#instrument_manager ⇒ Object
readonly
Returns the value of attribute instrument_manager.
-
#options ⇒ Object
options passed to the agent when
#start
is called.
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
- #background_worker_running? ⇒ Boolean
- #error_service_background_worker_running? ⇒ Boolean
-
#force? ⇒ Boolean
If true, the agent will start regardless of safety checks.
-
#initialize(options = {}) ⇒ Agent
constructor
First call of the agent.
-
#install(force = false) ⇒ Object
Finishes setting up the instrumentation, configuration, and attempts to start the agent.
-
#install_app_server_integration ⇒ Object
This sets up the background worker thread to run at the correct time, either immediately, or after a fork into the actual unicorn/puma/etc worker.
-
#install_background_job_integrations ⇒ Object
Attempts to install all background job integrations.
- #log_environment ⇒ Object
- #logger ⇒ Object
-
#should_load_instruments? ⇒ Boolean
monitor is the key configuration here.
-
#start(opts = {}) ⇒ Object
Unconditionally starts the agent.
-
#start_background_worker(quiet = false) ⇒ 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.
- #start_error_service_background_worker ⇒ Object
- #stop_background_worker ⇒ Object
Constructor Details
#initialize(options = {}) ⇒ Agent
First call of the agent. Does very little so that the object can be created, and exist.
25 26 27 28 |
# File 'lib/scout_apm/agent.rb', line 25 def initialize( = {}) @options = @context = ScoutApm::AgentContext.new end |
Instance Attribute Details
#context ⇒ Object (readonly)
Returns the value of attribute context.
13 14 15 |
# File 'lib/scout_apm/agent.rb', line 13 def context @context end |
#instrument_manager ⇒ Object (readonly)
Returns the value of attribute instrument_manager.
17 18 19 |
# File 'lib/scout_apm/agent.rb', line 17 def instrument_manager @instrument_manager end |
#options ⇒ Object
options passed to the agent when #start
is called.
15 16 17 |
# File 'lib/scout_apm/agent.rb', line 15 def @options 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.
20 21 22 |
# File 'lib/scout_apm/agent.rb', line 20 def self.instance( = {}) @@instance ||= self.new() end |
Instance Method Details
#background_worker_running? ⇒ Boolean
197 198 199 200 201 202 |
# File 'lib/scout_apm/agent.rb', line 197 def background_worker_running? @background_worker_thread && @background_worker_thread.alive? && @background_worker && @background_worker.running? end |
#error_service_background_worker_running? ⇒ Boolean
217 218 219 220 221 222 |
# File 'lib/scout_apm/agent.rb', line 217 def error_service_background_worker_running? @error_service_background_worker_thread && @error_service_background_worker_thread.alive? && @error_service_background_worker && @error_service_background_worker.running? end |
#force? ⇒ Boolean
If true, the agent will start regardless of safety checks.
123 124 125 |
# File 'lib/scout_apm/agent.rb', line 123 def force? @options[:force] end |
#install(force = false) ⇒ Object
Finishes setting up the instrumentation, configuration, and attempts to start the agent.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/scout_apm/agent.rb', line 35 def install(force=false) context.config = ScoutApm::Config.with_file(context, context.config.value("config_file")) logger.info "Scout Agent [#{ScoutApm::VERSION}] Initialized" if should_load_instruments? || force instrument_manager.install! install_background_job_integrations install_app_server_integration else logger.info "Not Loading Instruments" end logger.info "Scout Agent [#{ScoutApm::VERSION}] Installed" context.installed! @preconditions = ScoutApm::Agent::Preconditions.new if @preconditions.check?(context) || force start end end |
#install_app_server_integration ⇒ Object
This sets up the background worker thread to run at the correct time, either immediately, or after a fork into the actual unicorn/puma/etc worker
117 118 119 120 |
# File 'lib/scout_apm/agent.rb', line 117 def install_app_server_integration context.environment.app_server_integration.install logger.info "Installed Application Server Integration [#{context.environment.app_server}]." end |
#install_background_job_integrations ⇒ Object
Attempts to install all background job integrations. This can come up if an app has both Resque and Sidekiq - we want both to be installed if possible, it’s no harm to have the “wrong” one also installed while running.
107 108 109 110 111 112 |
# File 'lib/scout_apm/agent.rb', line 107 def install_background_job_integrations context.environment.background_job_integrations.each do |int| int.install logger.info "Installed Background Job Integration [#{int.name}]" end end |
#log_environment ⇒ Object
92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/scout_apm/agent.rb', line 92 def log_environment bg_names = context.environment.background_job_integrations.map{|bg| bg.name }.join(", ") logger.info( "Scout Agent [#{ScoutApm::VERSION}] starting for [#{context.environment.application_name}] " + "Framework [#{context.environment.framework}] " + "App Server [#{context.environment.app_server}] " + "Background Job Framework [#{bg_names}] " + "Hostname [#{context.environment.hostname}]" ) end |
#logger ⇒ Object
30 31 32 |
# File 'lib/scout_apm/agent.rb', line 30 def logger context.logger end |
#should_load_instruments? ⇒ Boolean
monitor is the key configuration here. If it is true, then we want the instruments. If it is false, we mostly don’t want them, unless you’re asking for devtrace (ie. not reporting to apm servers as a real app, but only for local browsers).
140 141 142 143 |
# File 'lib/scout_apm/agent.rb', line 140 def should_load_instruments? return true if context.config.value('dev_trace') context.config.value('monitor') end |
#start(opts = {}) ⇒ Object
Unconditionally starts the agent. This includes verifying instruments are installed, and starting the background worker.
The monitor precondition is checked explicitly, and we will never start with monitor = false
This does not attempt to start twice
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/scout_apm/agent.rb', line 64 def start(opts={}) return unless context.config.value('monitor') if context.started? start_background_worker unless background_worker_running? start_error_service_background_worker unless error_service_background_worker_running? return end install unless context.installed? instrument_manager.install! if should_load_instruments? context.started! log_environment # Save it into a variable to prevent it from ever running twice @app_server_load ||= AppServerLoad.new(context).run start_background_worker start_error_service_background_worker end |
#start_background_worker(quiet = false) ⇒ 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.
> true if thread & worker got started
> false if it wasn’t started (either due to already running, or other preconditions)
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/scout_apm/agent.rb', line 153 def start_background_worker(quiet=false) if !context.config.value('monitor') logger.debug "Not starting background worker as monitoring isn't enabled." unless quiet return false end if background_worker_running? logger.info "Not starting background worker, already started" unless quiet return false end if context.shutting_down? logger.info "Not starting background worker, already in process of shutting down" unless quiet return false end logger.info "Initializing worker thread." ScoutApm::Agent::ExitHandler.new(context).install periodic_work = ScoutApm::PeriodicWork.new(context) @background_worker = ScoutApm::BackgroundWorker.new(context) @background_worker_thread = Thread.new do @background_worker.start { periodic_work.run } end return true 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.
131 132 133 134 |
# File 'lib/scout_apm/agent.rb', line 131 def start_background_worker? return true if force? return !context.environment.forking? end |
#start_error_service_background_worker ⇒ Object
206 207 208 209 210 211 212 213 214 215 |
# File 'lib/scout_apm/agent.rb', line 206 def start_error_service_background_worker periodic_work = ScoutApm::ErrorService::PeriodicWork.new(context) @error_service_background_worker = ScoutApm::BackgroundWorker.new(context, ERROR_SEND_FREQUENCY) @error_service_background_worker_thread = Thread.new do @error_service_background_worker.start { periodic_work.run } end end |
#stop_background_worker ⇒ Object
185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/scout_apm/agent.rb', line 185 def stop_background_worker if @background_worker logger.info("Stopping background worker") @background_worker.stop context.store.write_to_layaway(context.layaway, :force) if @background_worker_thread.alive? @background_worker_thread.wakeup @background_worker_thread.join end end end |