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
- @@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
-
#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.
- #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
195 196 197 198 199 200 |
# File 'lib/scout_apm/agent.rb', line 195 def background_worker_running? @background_worker_thread && @background_worker_thread.alive? && @background_worker && @background_worker.running? end |
#force? ⇒ Boolean
If true, the agent will start regardless of safety checks.
121 122 123 |
# File 'lib/scout_apm/agent.rb', line 121 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
115 116 117 118 |
# File 'lib/scout_apm/agent.rb', line 115 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.
105 106 107 108 109 110 |
# File 'lib/scout_apm/agent.rb', line 105 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
90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/scout_apm/agent.rb', line 90 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).
138 139 140 141 |
# File 'lib/scout_apm/agent.rb', line 138 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 |
# 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? 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 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)
151 152 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 |
# File 'lib/scout_apm/agent.rb', line 151 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.
129 130 131 132 |
# File 'lib/scout_apm/agent.rb', line 129 def start_background_worker? return true if force? return !context.environment.forking? end |
#stop_background_worker ⇒ Object
183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/scout_apm/agent.rb', line 183 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 |