Module: TingYun::Agent::InstanceMethods::Start

Included in:
TingYun::Agent::InstanceMethods
Defined in:
lib/ting_yun/agent/instance_methods/start.rb

Instance Method Summary collapse

Instance Method Details

#after_fork(options = {}) ⇒ Object

This method should be called in a forked process after a fork. It assumes the parent process initialized the agent, but does not assume the agent started.

The call is idempotent, but not re-entrant.

  • It clears any metrics carried over from the parent process

  • Restarts the sampler thread if necessary

  • Initiates a new agent run and worker loop unless that was done in the parent process and :force_reconnect is not true

Options:

  • :force_reconnect => true to force the spawned process to establish a new connection, such as when forking a long running process. The default is false–it will only connect to the server if the parent had not connected.

  • :keep_retrying => false if we try to initiate a new connection, this tells me to only try it once so this method returns quickly if there is some kind of latency with the server.



194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/ting_yun/agent/instance_methods/start.rb', line 194

def after_fork(options={})
  needs_restart = false
  @after_fork_lock.synchronize do
    needs_restart = @dispatcher.needs_restart?
    @dispatcher.mark_started
  end

  return if !needs_restart ||
      !Agent.config[:'nbs.agent_enabled'] ||
      !Agent.config[:monitor_mode] ||
      disconnected?

  ::TingYun::Agent.logger.debug "Starting the worker thread in #{Process.pid} (parent #{Process.ppid}) after forking."

  # Clear out locks and stats left over from parent process
  reset_objects_with_locks
  drop_buffered_data

  setup_and_start_agent(options)
end

#agent_should_start?Boolean

Check to see if the agent should start, returning true if it should. should hava the vaild app_name, unstart-state and able to start

Returns:

  • (Boolean)


14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/ting_yun/agent/instance_methods/start.rb', line 14

def agent_should_start?
  return false if already_started? || disabled?
  unless app_name_configured?
    TingYun::Agent.logger.error "No application name configured.",
                       "The Agent cannot start without at least one. Please check your ",
                       "tingyun.yml and ensure that it is valid and has at least one ",
                       "value set for app_name in the",
                       "environment."
    return false
  end
  return true
end

#already_started?Boolean

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

Returns:

  • (Boolean)


32
33
34
35
36
37
# File 'lib/ting_yun/agent/instance_methods/start.rb', line 32

def already_started?
  if started?
    TingYun::Agent.logger.info("Agent Started Already!")
    true
  end
end

#app_name_configured?Boolean

Logs the configured application names

Returns:

  • (Boolean)


130
131
132
133
# File 'lib/ting_yun/agent/instance_methods/start.rb', line 130

def app_name_configured?
  names = TingYun::Agent.config.app_names
  return names.respond_to?(:any?) && names.any?
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



151
152
153
154
155
# File 'lib/ting_yun/agent/instance_methods/start.rb', line 151

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

#correct_license_lengthObject

A license key is an arbitrary 40 character string, usually looks something like a SHA1 hash



113
114
115
116
117
118
119
120
121
122
# File 'lib/ting_yun/agent/instance_methods/start.rb', line 113

def correct_license_length
  key = TingYun::Agent.config[:license_key]

  if key.length > 0
    true
  else
    TingYun::Agent.logger.error("Invalid license key: #{key}")
    false
  end
end

#cpu_and_memoryObject



215
216
217
# File 'lib/ting_yun/agent/instance_methods/start.rb', line 215

def cpu_and_memory
  @middleware.load_samplers
end

#disabled?Boolean

The agent is disabled when it is not force enabled by the ‘nbs.agent_enabled’ option (e.g. in a manual start), or enabled normally through the configuration file

Returns:

  • (Boolean)


42
43
44
# File 'lib/ting_yun/agent/instance_methods/start.rb', line 42

def disabled?
  !TingYun::Agent.config[:'nbs.agent_enabled']
end

#has_correct_license_key?Boolean

A correct license key exists and is of the proper length

Returns:

  • (Boolean)


125
126
127
# File 'lib/ting_yun/agent/instance_methods/start.rb', line 125

def has_correct_license_key?
  has_license_key? && correct_license_length
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)


101
102
103
104
105
106
107
108
109
# File 'lib/ting_yun/agent/instance_methods/start.rb', line 101

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

#is_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)


139
140
141
142
143
144
145
146
# File 'lib/ting_yun/agent/instance_methods/start.rb', line 139

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

#log_app_nameObject



69
70
71
# File 'lib/ting_yun/agent/instance_methods/start.rb', line 69

def log_app_name
  TingYun::Agent.logger.info "Application: #{TingYun::Agent.config.app_names.join(", ")}"
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



59
60
61
62
63
64
65
66
67
# File 'lib/ting_yun/agent/instance_methods/start.rb', line 59

def log_dispatcher
  dispatcher_name = TingYun::Agent.config[:dispatcher].to_s

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

#log_environmentObject



52
53
54
# File 'lib/ting_yun/agent/instance_methods/start.rb', line 52

def log_environment
  Agent.logger.info "Environment: #{::TingYun::Frameworks.framework.env}"
end

#log_startupObject



46
47
48
49
50
# File 'lib/ting_yun/agent/instance_methods/start.rb', line 46

def log_startup
  log_environment
  log_dispatcher
  log_app_name
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



84
85
86
# File 'lib/ting_yun/agent/instance_methods/start.rb', line 84

def log_version_and_pid
  TingYun::Agent.logger.debug "Ting Yun Ruby Agent #{TingYun::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)


90
91
92
93
94
95
96
97
# File 'lib/ting_yun/agent/instance_methods/start.rb', line 90

def monitoring?
  if TingYun::Agent.config[:monitor_mode]
    true
  else
    TingYun::Agent.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.



161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/ting_yun/agent/instance_methods/start.rb', line 161

def setup_and_start_agent(options={})
  @started = true
  @dispatcher.mark_started
  generate_environment_report
  install_exit_handler
  cpu_and_memory

  if TingYun::Agent.config[:sync_startup]
    connect_in_sync
  else
    start_worker_thread(options)
  end
end

#sinatra_app?Boolean

Returns:

  • (Boolean)


73
74
75
76
77
78
79
# File 'lib/ting_yun/agent/instance_methods/start.rb', line 73

def sinatra_app?
  (
  defined?(Sinatra::Application) &&
      Sinatra::Application.respond_to?(:run) &&
      Sinatra::Application.run?
  )
end

#started?Boolean

Returns:

  • (Boolean)


27
28
29
# File 'lib/ting_yun/agent/instance_methods/start.rb', line 27

def started?
  @started
end