Module: OneApm::Agent::Agent::Start

Included in:
OneApm::Agent::Agent
Defined in:
lib/one_apm/agent/agent/start.rb

Instance Method Summary collapse

Instance Method Details

#already_started?Boolean

Check whether we have already started, which is an error condition

Returns:

  • (Boolean)


41
42
43
44
45
46
# File 'lib/one_apm/agent/agent/start.rb', line 41

def already_started?
  if started?
    OneApm::Manager.logger.error("Agent Started Already!")
    true
  end
end

#app_name_configured?Boolean

Logs the configured application names

Returns:

  • (Boolean)


77
78
79
80
# File 'lib/one_apm/agent/agent/start.rb', line 77

def app_name_configured?
  app_name = OneApm::Manager.config.app_name
  return app_name.respond_to?(:empty?) && !app_name.empty?
end

#check_config_and_start_agentObject

Sanity-check the agent configuration and start the agent, setting up the worker thread and the exit handler to shut down the agent



11
12
13
14
15
# File 'lib/one_apm/agent/agent/start.rb', line 11

def check_config_and_start_agent
  return unless monitoring? && has_correct_license_key?
  return if using_forking_dispatcher?
  setup_and_start_agent
end

#connect_in_foregroundObject

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



93
94
95
# File 'lib/one_apm/agent/agent/start.rb', line 93

def connect_in_foreground
  OneApm::Manager.disable_all_tracing { connect(:keep_retrying => false) }
end

#defer_for_background_jobs?Boolean

Returns:

  • (Boolean)


151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/one_apm/agent/agent/start.rb', line 151

def defer_for_background_jobs?
  if defer_for_delayed_job?
    OneApm::Manager.logger.debug "Deferring startup for DelayedJob"
    return true
  end

  if defer_for_resque?
    OneApm::Manager.logger.debug "Deferring startup for Resque in case it daemonizes"
    return true
  end

  false
end

#defer_for_delayed_job?Boolean

Returns:

  • (Boolean)


167
168
169
170
# File 'lib/one_apm/agent/agent/start.rb', line 167

def defer_for_delayed_job?
  OneApm::Manager.config[:dispatcher] == :delayed_job &&
    !OneApm::DelayedJobInjection.worker_name
end

#defer_for_resque?Boolean

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)

Returns:

  • (Boolean)


175
176
177
178
179
# File 'lib/one_apm/agent/agent/start.rb', line 175

def defer_for_resque?
  OneApm::Manager.config[:dispatcher] == :resque &&
    OneApm::LanguageSupport.can_fork? &&
    !OneApm::Support::ForkedProcessChannel.listener.started?
end

#disabled?Boolean

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

Returns:

  • (Boolean)


72
73
74
# File 'lib/one_apm/agent/agent/start.rb', line 72

def disabled?
  !Manager.config[:agent_enabled]
end

#has_correct_license_key?Boolean

A correct license key exists and is of the proper length

Returns:

  • (Boolean)


135
136
137
# File 'lib/one_apm/agent/agent/start.rb', line 135

def has_correct_license_key?
  has_license_key?
end

#has_license_key?Boolean

Tell the user when the license key is missing so they can fix it by adding it to the file

Returns:

  • (Boolean)


124
125
126
127
128
129
130
131
132
# File 'lib/one_apm/agent/agent/start.rb', line 124

def has_license_key?
  if OneApm::Manager.config[:license_key] && OneApm::Manager.config[:license_key].length > 0
    true
  else
    OneApm::Manager.logger.warn("No license key found. " +
      "This often means your oneapm.yml file was not found, or it lacks a section for the running environment, '#{OneApm::Probe.instance.env}'. You may also want to try linting your oneapm.yml to ensure it is valid YML.")
    false
  end
end

#in_resque_child_process?Boolean

Returns:

  • (Boolean)


181
182
183
# File 'lib/one_apm/agent/agent/start.rb', line 181

def in_resque_child_process?
  @service.is_a?(OneApm::Collector::ForkedProcessService)
end

#install_exit_handlerObject

Installs our exit handler, which exploits the weird behavior of at_exit blocks to make sure it runs last, by doing an at_exit within an at_exit block.



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/one_apm/agent/agent/start.rb', line 51

def install_exit_handler
  if OneApm::Manager.config[:send_data_on_exit] && !weird_ruby?
    at_exit do
      # Workaround for MRI 1.9 bug that loses exit codes in at_exit blocks.
      # This is necessary to get correct exit codes for the agent's
      # test suites.
      # http://bugs.ruby-lang.org/issues/5218
      if defined?(RUBY_ENGINE) && RUBY_ENGINE == "ruby" && RUBY_VERSION.match(/^1\.9/)
        exit_status = $!.status if $!.is_a?(SystemExit)
        shutdown
        exit exit_status if exit_status
      else
        shutdown
      end
    end
  end
end

#log_app_nameObject



219
220
221
# File 'lib/one_apm/agent/agent/start.rb', line 219

def log_app_name
  OneApm::Manager.logger.info "Application: #{Manager.config.app_name}"
end

#log_dispatcherObject

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



209
210
211
212
213
214
215
216
217
# File 'lib/one_apm/agent/agent/start.rb', line 209

def log_dispatcher
  dispatcher_name = OneApm::Manager.config[:dispatcher].to_s

  if dispatcher_name.empty?
    OneApm::Manager.logger.info 'No known dispatcher detected.'
  else
    OneApm::Manager.logger.info "Dispatcher: #{dispatcher_name}"
  end
end

#log_environmentObject

Log the environment the app thinks it’s running in. Useful in debugging, as this is the key for config YAML lookups.



202
203
204
# File 'lib/one_apm/agent/agent/start.rb', line 202

def log_environment
  OneApm::Manager.logger.info "Environment: #{OneApm::Probe.instance.env}"
end

#log_ignore_url_regexesObject



228
229
230
231
232
233
234
# File 'lib/one_apm/agent/agent/start.rb', line 228

def log_ignore_url_regexes
  regexes = OneApm::Manager.config[:'rules.ignore_url_regexes']

  unless regexes.empty?
    OneApm::Manager.logger.info "Ignoring URLs that match the following regexes: #{regexes.map(&:inspect).join(", ")}."
  end
end

#log_startupObject

Log startup information that we almost always want to know



186
187
188
189
190
191
# File 'lib/one_apm/agent/agent/start.rb', line 186

def log_startup
  log_environment
  log_dispatcher
  log_app_name
  log_tier_name
end

#log_tier_nameObject



223
224
225
# File 'lib/one_apm/agent/agent/start.rb', line 223

def log_tier_name
  OneApm::Manager.logger.info "Tiername: #{Manager.config.tier_names.join(", ")}"
end

#log_version_and_pidObject

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



196
197
198
# File 'lib/one_apm/agent/agent/start.rb', line 196

def log_version_and_pid
  OneApm::Manager.logger.debug "OneApm Ruby Agent #{OneApm::VERSION::STRING} Initialized: pid = #{$$}"
end

#monitoring?Boolean

Warn the user if they have configured their agent not to send data, that way we can see this clearly in the log file

Returns:

  • (Boolean)


113
114
115
116
117
118
119
120
# File 'lib/one_apm/agent/agent/start.rb', line 113

def monitoring?
  if OneApm::Manager.config[:monitor_mode]
    true
  else
    OneApm::Manager.logger.warn('Agent configured not to send data in this environment.')
    false
  end
end

#setup_and_start_agent(options = {}) ⇒ Object

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.



21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/one_apm/agent/agent/start.rb', line 21

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 OneApm::Manager.config[:disable_samplers]
  end

  connect_in_foreground if OneApm::Manager.config[:sync_startup]
  start_worker_thread(options)
end

#started?Boolean

True if we have initialized and completed ‘start’

Returns:

  • (Boolean)


36
37
38
# File 'lib/one_apm/agent/agent/start.rb', line 36

def started?
  @started
end

#tier_name_configured?Boolean

Logs the configured application tier names

Returns:

  • (Boolean)


83
84
85
86
# File 'lib/one_apm/agent/agent/start.rb', line 83

def tier_name_configured?
  tier_names = OneApm::Manager.config.tier_names
  return tier_names.respond_to?(:any?) && tier_names.any?
end

#using_forking_dispatcher?Boolean

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

Returns:

  • (Boolean)


142
143
144
145
146
147
148
149
# File 'lib/one_apm/agent/agent/start.rb', line 142

def using_forking_dispatcher?
  if [:puma, :passenger, :rainbows, :unicorn].include? OneApm::Manager.config[:dispatcher]
    OneApm::Manager.logger.info "Deferring startup of agent reporting thread because #{Manager.config[:dispatcher]} may fork."
    true
  else
    false
  end
end

#using_sinatra?Boolean

If we’re using sinatra, old versions run in an at_exit block so we should probably know that

Returns:

  • (Boolean)


99
100
101
# File 'lib/one_apm/agent/agent/start.rb', line 99

def using_sinatra?
  defined?(Sinatra::Application)
end

#weird_ruby?Boolean

we should not set an at_exit block if people are using these as they don’t do standard at_exit behavior per MRI/YARV

Returns:

  • (Boolean)


105
106
107
108
109
# File 'lib/one_apm/agent/agent/start.rb', line 105

def weird_ruby?
  OneApm::LanguageSupport.using_engine?('rbx') ||
    OneApm::LanguageSupport.using_engine?('jruby') ||
    using_sinatra?
end