Module: NewRelic::Agent::Agent::InstanceMethods

Includes:
Connect, Start, StartWorkerThread
Included in:
NewRelic::Agent::Agent
Defined in:
lib/new_relic/agent/agent.rb

Overview

Holds all the methods defined on NewRelic::Agent::Agent instances

Defined Under Namespace

Modules: Connect, Start, StartWorkerThread

Instance Attribute Summary collapse

Attributes included from Connect

#connect_attempts, #connect_retry_period

Instance Method Summary collapse

Methods included from Connect

#apdex_f, #apdex_f_threshold?, #config_transaction_tracer, #configure_error_collector!, #configure_transaction_tracer!, #connect_settings, #connect_to_server, #disconnect, #enable_random_samples!, #environment_for_connect, #finish_setup, #get_retry_period, #handle_license_error, #increment_retry_period!, #log_connection!, #log_error, #log_seed_token, #log_sql_transmission_warning?, #query_server_for_configuration, #set_collector_host!, #set_sql_recording!, #should_keep_retrying?, #should_retry?, #tried_to_connect?, #validate_settings

Methods included from StartWorkerThread

#catch_errors, #check_sql_sampler_status, #check_transaction_sampler_status, #create_and_run_worker_loop, #deferred_work!, #handle_force_disconnect, #handle_force_restart, #handle_other_error, #handle_server_connection_problem, #log_worker_loop_start

Methods included from Start

#already_started?, #check_config_and_start_agent, #connect_in_foreground, #correct_license_length, #disabled?, #has_correct_license_key?, #has_license_key?, #install_exit_handler, #log_app_names, #log_dispatcher, #log_if, #log_unless, #log_version_and_pid, #monitoring?, #notify_log_file_location, #using_forking_dispatcher?, #using_sinatra?, #weird_ruby?

Instance Attribute Details

#beacon_configurationObject (readonly)

a configuration for the Real User Monitoring system - handles things like static setup of the header for inclusion into pages



83
84
85
# File 'lib/new_relic/agent/agent.rb', line 83

def beacon_configuration
  @beacon_configuration
end

#error_collectorObject (readonly)

error collector is a simple collection of recorded errors



70
71
72
# File 'lib/new_relic/agent/agent.rb', line 70

def error_collector
  @error_collector
end

#metric_idsObject (readonly)

a cached set of metric_ids to save the collector some time - it returns a metric id for every metric name we send it, and in the future we transmit using the metric id only



76
77
78
# File 'lib/new_relic/agent/agent.rb', line 76

def metric_ids
  @metric_ids
end

#obfuscatorObject (readonly)

holds a proc that is used to obfuscate sql statements



63
64
65
# File 'lib/new_relic/agent/agent.rb', line 63

def obfuscator
  @obfuscator
end

#record_sqlObject (readonly)

whether we should record raw, obfuscated, or no sql



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

def record_sql
  @record_sql
end

#sql_samplerObject (readonly)

Returns the value of attribute sql_sampler.



68
69
70
# File 'lib/new_relic/agent/agent.rb', line 68

def sql_sampler
  @sql_sampler
end

#stats_engineObject (readonly)

the statistics engine that holds all the timeslice data



65
66
67
# File 'lib/new_relic/agent/agent.rb', line 65

def stats_engine
  @stats_engine
end

#transaction_samplerObject (readonly)

the transaction sampler that handles recording transactions



67
68
69
# File 'lib/new_relic/agent/agent.rb', line 67

def transaction_sampler
  @transaction_sampler
end

#url_rulesObject (readonly)

in theory a set of rules applied by the agent to the output of its metrics. Currently unimplemented



79
80
81
# File 'lib/new_relic/agent/agent.rb', line 79

def url_rules
  @url_rules
end

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.



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/new_relic/agent/agent.rb', line 160

def after_fork(options={})

  # @connected gets false after we fail to connect or have an error
  # connecting.  @connected has nil if we haven't finished trying to connect.
  # or we didn't attempt a connection because this is the master process

  # log.debug "Agent received after_fork notice in #$$: [#{control.agent_enabled?}; monitor=#{control.monitor_mode?}; connected: #{@connected.inspect}; thread=#{@worker_thread.inspect}]"
  return if !control.agent_enabled? or
    !control.monitor_mode? or
    @connected == false or
    @worker_thread && @worker_thread.alive?

  log.info "Starting the worker thread in #$$ after forking."

  # Clear out stats that are left over from parent process
  reset_stats

  # Don't ever check to see if this is a spawner.  If we're in a forked process
  # I'm pretty sure we're not also forking new instances.
  start_worker_thread(options)
  @stats_engine.start_sampler_thread
end

#connected?Boolean

Return nil if not yet connected, true if successfully started and false if we failed to start.

Returns:

  • (Boolean)


190
191
192
# File 'lib/new_relic/agent/agent.rb', line 190

def connected?
  @connected
end

#end_transactionObject

Tells the statistics engine we are ending a transaction



235
236
237
# File 'lib/new_relic/agent/agent.rb', line 235

def end_transaction
  @stats_engine.end_transaction
end

#logObject

Shorthand to the NewRelic::Agent.logger method



277
278
279
# File 'lib/new_relic/agent/agent.rb', line 277

def log
  NewRelic::Agent.logger
end

#merge_data_from(data) ⇒ Object

Accepts data as provided by the serialize method and merges it into our current collection of data to send. Can be dangerous if we re-merge the same data more than once - it will be sent multiple times.



909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
# File 'lib/new_relic/agent/agent.rb', line 909

def merge_data_from(data)
  metrics, transaction_traces, errors = data
  @stats_engine.merge_data(metrics) if metrics
  if transaction_traces
    if @traces
      @traces = @traces + transaction_traces
    else
      @traces = transaction_traces
    end
  end
  if errors
    if @unsent_errors
      @unsent_errors = @unsent_errors + errors
    else
      @unsent_errors = errors
    end
  end
end

#pop_trace_execution_flagObject

Pop the current trace execution status. Restore trace execution status to what it was before we pushed the current flag.



272
273
274
# File 'lib/new_relic/agent/agent.rb', line 272

def pop_trace_execution_flag
  Thread.current[:newrelic_untraced].pop if Thread.current[:newrelic_untraced]
end

#push_trace_execution_flag(should_trace = false) ⇒ Object

Push flag indicating whether we should be tracing in this thread. This uses a stack which allows us to disable tracing children of a transaction without affecting the tracing of the whole transaction



261
262
263
264
265
266
267
268
# File 'lib/new_relic/agent/agent.rb', line 261

def push_trace_execution_flag(should_trace=false)
  value = Thread.current[:newrelic_untraced]
  if (value.nil?)
    Thread.current[:newrelic_untraced] = []
  end

  Thread.current[:newrelic_untraced] << should_trace
end

#record_transaction(duration_seconds, options = {}) ⇒ Object

fakes out a transaction that did not happen in this process by creating apdex, summary metrics, and recording statistics for the transaction

This method is deprecated - it may be removed in future versions of the agent



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/new_relic/agent/agent.rb', line 110

def record_transaction(duration_seconds, options={})
  is_error = options['is_error'] || options['error_message'] || options['exception']
  metric = options['metric']
  metric ||= options['uri'] # normalize this with url rules
  raise "metric or uri arguments required" unless metric
  metric_info = NewRelic::MetricParser::MetricParser.for_metric_named(metric)

  if metric_info.is_web_transaction?
    NewRelic::Agent::Instrumentation::MetricFrame.record_apdex(metric_info, duration_seconds, duration_seconds, is_error)
  end
  metrics = metric_info.summary_metrics

  metrics << metric
  metrics.each do |name|
    stats = stats_engine.get_stats_no_scope(name)
    stats.record_data_point(duration_seconds)
  end

  if is_error
    if options['exception']
      e = options['exception']
    elsif options['error_message']
      e = Exception.new options['error_message']
    else
      e = Exception.new 'Unknown Error'
    end
    error_collector.notice_error e, :uri => options['uri'], :metric => metric
  end
  # busy time ?
end

#reset_statsObject

Clear out the metric data, errors, and transaction traces, making sure the agent is in a fresh state



439
440
441
442
443
444
445
446
# File 'lib/new_relic/agent/agent.rb', line 439

def reset_stats
  @stats_engine.reset_stats
  @unsent_errors = []
  @traces = nil
  @unsent_timeslice_data = {}
  @last_harvest_time = Time.now
  @launch_time = Time.now
end

#serializeObject

Serialize all the important data that the agent might want to send to the server. We could be sending this to file ( common in short-running background transactions ) or alternately we could serialize via a pipe or socket to a local aggregation device



894
895
896
897
898
899
900
901
902
# File 'lib/new_relic/agent/agent.rb', line 894

def serialize
  accumulator = []
  accumulator[1] = harvest_transaction_traces if @transaction_sampler
  accumulator[2] = harvest_errors if @error_collector
  accumulator[0] = harvest_timeslice_data
  reset_stats
  @metric_ids = {}
  accumulator
end

#set_record_sql(should_record) ⇒ Object

Sets a thread local variable as to whether we should or should not record sql in the current thread. Returns the previous value, if there is one



242
243
244
245
246
# File 'lib/new_relic/agent/agent.rb', line 242

def set_record_sql(should_record)
  prev = Thread::current[:record_sql]
  Thread::current[:record_sql] = should_record
  prev.nil? || prev
end

#set_record_tt(should_record) ⇒ Object

Sets a thread local variable as to whether we should or should not record transaction traces in the current thread. Returns the previous value, if there is one



251
252
253
254
255
# File 'lib/new_relic/agent/agent.rb', line 251

def set_record_tt(should_record)
  prev = Thread::current[:record_tt]
  Thread::current[:record_tt] = should_record
  prev.nil? || prev
end

#shutdown(options = {}) ⇒ Object

Attempt a graceful shutdown of the agent, running the worker loop if it exists and is running.

Options: :force_send => (true/false) # force the agent to send data before shutting down



200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/new_relic/agent/agent.rb', line 200

def shutdown(options={})
  run_loop_before_exit = options.fetch(:force_send, false)
  return if not started?
  if @worker_loop
    @worker_loop.run_task if run_loop_before_exit
    @worker_loop.stop

    log.debug "Starting Agent shutdown"

    # if litespeed, then ignore all future SIGUSR1 - it's
    # litespeed trying to shut us down

    if control.dispatcher == :litespeed
      Signal.trap("SIGUSR1", "IGNORE")
      Signal.trap("SIGTERM", "IGNORE")
    end

    begin
      NewRelic::Agent.disable_all_tracing do
        graceful_disconnect
      end
    rescue => e
      log.error e
      log.error e.backtrace.join("\n")
    end
  end
  @started = nil
end

#startObject

Logs a bunch of data and starts the agent, if needed



425
426
427
428
429
430
431
432
433
434
435
# File 'lib/new_relic/agent/agent.rb', line 425

def start
  return if already_started? || disabled?
  @started = true
  @local_host = determine_host
  log_dispatcher
  log_app_names
  config_transaction_tracer
  check_config_and_start_agent
  log_version_and_pid
  notify_log_file_location
end

#start_transactionObject

Tells the statistics engine we are starting a new transaction



230
231
232
# File 'lib/new_relic/agent/agent.rb', line 230

def start_transaction
  @stats_engine.start_transaction
end

#started?Boolean

True if we have initialized and completed ‘start’

Returns:

  • (Boolean)


184
185
186
# File 'lib/new_relic/agent/agent.rb', line 184

def started?
  @started
end

#unsent_errors_sizeObject

Returns the length of the unsent errors array, if it exists, otherwise nil



87
88
89
# File 'lib/new_relic/agent/agent.rb', line 87

def unsent_errors_size
  @unsent_errors.length if @unsent_errors
end

#unsent_timeslice_dataObject

Initializes the unsent timeslice data hash, if needed, and returns the number of keys it contains



99
100
101
102
# File 'lib/new_relic/agent/agent.rb', line 99

def unsent_timeslice_data
  @unsent_timeslice_data ||= {}
  @unsent_timeslice_data.keys.length
end

#unsent_traces_sizeObject

Returns the length of the traces array, if it exists, otherwise nil



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

def unsent_traces_size
  @traces.length if @traces
end