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

Instance Method Summary collapse

Methods included from Connect

#add_rules_to_engine, #apdex_f, #connect_retry_period, #connect_settings, #connect_to_server, #connected?, #disconnect, #disconnected?, #environment_for_connect, #finish_setup, #generate_environment_report, #handle_license_error, #handle_unrecoverable_agent_error, #log_collector_messages, #log_connection!, #log_error, #note_connect_failure, #query_server_for_configuration, #should_connect?

Methods included from StartWorkerThread

#catch_errors, #create_and_run_worker_loop, #deferred_work!, #handle_force_disconnect, #handle_force_restart, #handle_other_error, #handle_server_connection_problem, #log_worker_loop_start, #reset_harvest_locks, #synchronize_with_harvest

Methods included from Start

#already_started?, #app_name_configured?, #check_config_and_start_agent, #connect_in_foreground, #correct_license_length, #defer_for_resque?, #disabled?, #has_correct_license_key?, #has_license_key?, #install_exit_handler, #log_app_name, #log_dispatcher, #log_environment, #log_startup, #log_version_and_pid, #monitoring?, #using_forking_dispatcher?, #using_sinatra?, #weird_ruby?

Instance Attribute Details

#agent_command_routerObject (readonly)

manages agent commands we receive from the collector, and the handlers



85
86
87
# File 'lib/new_relic/agent/agent.rb', line 85

def agent_command_router
  @agent_command_router
end

#beacon_configurationObject (readonly)

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



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

def beacon_configuration
  @beacon_configuration
end

#cross_app_encoding_bytesObject (readonly)

Returns the value of attribute cross_app_encoding_bytes.



97
98
99
# File 'lib/new_relic/agent/agent.rb', line 97

def cross_app_encoding_bytes
  @cross_app_encoding_bytes
end

#cross_app_monitorObject (readonly)

Returns the value of attribute cross_app_monitor.



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

def cross_app_monitor
  @cross_app_monitor
end

#cross_process_idObject (readonly)

cross application tracing ids and encoding



96
97
98
# File 'lib/new_relic/agent/agent.rb', line 96

def cross_process_id
  @cross_process_id
end

#error_collectorObject (readonly)

error collector is a simple collection of recorded errors



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

def error_collector
  @error_collector
end

#eventsObject (readonly)

Global events dispatcher. This will provides our primary mechanism for agent-wide events, such as finishing configuration, error notification and request before/after from Rack.



104
105
106
# File 'lib/new_relic/agent/agent.rb', line 104

def events
  @events
end

#harvest_lockObject (readonly)

Returns the value of attribute harvest_lock.



110
111
112
# File 'lib/new_relic/agent/agent.rb', line 110

def harvest_lock
  @harvest_lock
end

#harvest_samplersObject (readonly)

Returns the value of attribute harvest_samplers.



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

def harvest_samplers
  @harvest_samplers
end

#metric_rulesObject (readonly)

Returns the value of attribute metric_rules.



109
110
111
# File 'lib/new_relic/agent/agent.rb', line 109

def metric_rules
  @metric_rules
end

#obfuscatorObject (readonly)

holds a proc that is used to obfuscate sql statements



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

def obfuscator
  @obfuscator
end

#record_sqlObject (readonly)

whether we should record raw, obfuscated, or no sql



90
91
92
# File 'lib/new_relic/agent/agent.rb', line 90

def record_sql
  @record_sql
end

#serviceObject

service for communicating with collector



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

def service
  @service
end

#sql_samplerObject (readonly)

Returns the value of attribute sql_sampler.



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

def sql_sampler
  @sql_sampler
end

#stats_engineObject (readonly)

the statistics engine that holds all the timeslice data



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

def stats_engine
  @stats_engine
end

#transaction_rulesObject (readonly)

Transaction and metric renaming rules as provided by the collector on connect. The former are applied during txns, the latter during harvest.



108
109
110
# File 'lib/new_relic/agent/agent.rb', line 108

def transaction_rules
  @transaction_rules
end

#transaction_samplerObject (readonly)

the transaction sampler that handles recording transactions



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

def transaction_sampler
  @transaction_sampler
end

Instance Method Details

#add_harvest_sampler(subclass) ⇒ Object



542
543
544
# File 'lib/new_relic/agent/agent.rb', line 542

def add_harvest_sampler(subclass)
  @harvest_samplers.add_sampler(subclass)
end

#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.



186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/new_relic/agent/agent.rb', line 186

def after_fork(options={})
  Agent.config.apply_config(NewRelic::Agent::Configuration::ManualSource.new(options), 1)

  if channel_id = options[:report_to_channel]
    @service = NewRelic::Agent::PipeService.new(channel_id)
    if connected?
      @connected_pid = $$
    else
      ::NewRelic::Agent.logger.debug("Child process #{$$} not reporting to non-connected parent.")
      @service.shutdown(Time.now)
      disconnect
    end
  end

  return if !Agent.config[:agent_enabled] ||
    !Agent.config[:monitor_mode] ||
    disconnected? ||
    @worker_thread && @worker_thread.alive?

  ::NewRelic::Agent.logger.debug "Starting the worker thread in #{$$} after forking."

  reset_objects_with_locks

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

  generate_environment_report
  start_worker_thread(options)
end

#agent_should_start?Boolean

Check to see if the agent should start, returning true if it should.

Returns:

  • (Boolean)


487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
# File 'lib/new_relic/agent/agent.rb', line 487

def agent_should_start?
  return false if already_started? || disabled?

  if defer_for_delayed_job?
    ::NewRelic::Agent.logger.debug "Deferring startup for DelayedJob"
    return false
  end

  if defer_for_resque?
    ::NewRelic::Agent.logger.debug "Deferring startup for Resque in case it daemonizes"
    return false
  end

  unless app_name_configured?
    NewRelic::Agent.logger.error "No application name configured.",
      "The Agent cannot start without at least one. Please check your ",
      "newrelic.yml and ensure that it is valid and has at least one ",
      "value set for app_name in the #{NewRelic::Control.instance.env} ",
      "environment."
    return false
  end

  return true
end

#defer_for_delayed_job?Boolean

Returns:

  • (Boolean)


481
482
483
484
# File 'lib/new_relic/agent/agent.rb', line 481

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

#end_transactionObject

Tells the statistics engine we are ending a transaction



264
265
266
# File 'lib/new_relic/agent/agent.rb', line 264

def end_transaction
  @stats_engine.end_transaction
end

#merge_data_from(data) ⇒ Object

Accepts an array of (metrics, transaction_traces, errors) 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.



863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
# File 'lib/new_relic/agent/agent.rb', line 863

def merge_data_from(data)
  metrics, transaction_traces, errors = data
  @stats_engine.merge!(metrics) if metrics
  if transaction_traces && transaction_traces.respond_to?(:any?) &&
      transaction_traces.any?
    if @traces
      @traces += transaction_traces
    else
      @traces = transaction_traces
    end
  end
  if errors && errors.respond_to?(:each)
    errors.each do |err|
      @error_collector.add_to_error_queue(err)
    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.



296
297
298
# File 'lib/new_relic/agent/agent.rb', line 296

def pop_trace_execution_flag
  TransactionState.get.pop_traced
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



290
291
292
# File 'lib/new_relic/agent/agent.rb', line 290

def push_trace_execution_flag(should_trace=false)
  TransactionState.get.push_traced(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



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/new_relic/agent/agent.rb', line 137

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::Transaction.record_apdex(metric_info, duration_seconds, duration_seconds, is_error)
  end
  metrics = metric_info.summary_metrics

  metrics << metric
  metrics.each do |name|
    NewRelic::Agent.record_metric(name, duration_seconds)
  end

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

#reset_objects_with_locksObject

Clear out state for any objects that we know lock from our parents This is necessary for cases where we’re in a forked child and Ruby might be holding locks for background thread that aren’t there anymore.



537
538
539
540
# File 'lib/new_relic/agent/agent.rb', line 537

def reset_objects_with_locks
  @stats_engine = NewRelic::Agent::StatsEngine.new
  reset_harvest_locks
end

#reset_statsObject

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



525
526
527
528
529
530
531
532
# File 'lib/new_relic/agent/agent.rb', line 525

def reset_stats
  @stats_engine.reset_stats
  @unsent_errors = []
  @traces = nil
  @unsent_timeslice_data = {}
  @last_harvest_time = Time.now
  @launch_time = Time.now
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



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

def set_record_sql(should_record)
  prev = TransactionState.get.record_sql
  TransactionState.get.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



280
281
282
283
284
# File 'lib/new_relic/agent/agent.rb', line 280

def set_record_tt(should_record)
  prev = TransactionState.get.record_tt
  TransactionState.get.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



226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/new_relic/agent/agent.rb', line 226

def shutdown(options={})
  run_loop_before_exit = Agent.config[:force_send]
  return if not started?
  if @worker_loop
    @worker_loop.run_task if run_loop_before_exit
    @worker_loop.stop
  end

  ::NewRelic::Agent.logger.info "Starting Agent shutdown"

  # if litespeed, then ignore all future SIGUSR1 - it's
  # litespeed trying to shut us down
  if Agent.config[:dispatcher] == :litespeed
    Signal.trap("SIGUSR1", "IGNORE")
    Signal.trap("SIGTERM", "IGNORE")
  end

  begin
    NewRelic::Agent.disable_all_tracing do
      graceful_disconnect
    end
  rescue => e
    ::NewRelic::Agent.logger.error e
  end
  NewRelic::Agent.config.remove_config do |config|
    config.class == NewRelic::Agent::Configuration::ManualSource ||
      config.class == NewRelic::Agent::Configuration::ServerSource
  end
  @started = nil
  Control.reset
end

#startObject

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



513
514
515
516
517
518
519
520
521
# File 'lib/new_relic/agent/agent.rb', line 513

def start
  return unless agent_should_start?

  @started = true
  @local_host = determine_host
  log_startup
  check_config_and_start_agent
  log_version_and_pid
end

#start_transactionObject

Tells the statistics engine we are starting a new transaction



259
260
261
# File 'lib/new_relic/agent/agent.rb', line 259

def start_transaction
  @stats_engine.start_transaction
end

#started?Boolean

True if we have initialized and completed ‘start’

Returns:

  • (Boolean)


217
218
219
# File 'lib/new_relic/agent/agent.rb', line 217

def started?
  @started
end

#unsent_errors_sizeObject

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



114
115
116
# File 'lib/new_relic/agent/agent.rb', line 114

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



126
127
128
129
# File 'lib/new_relic/agent/agent.rb', line 126

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



120
121
122
# File 'lib/new_relic/agent/agent.rb', line 120

def unsent_traces_size
  @traces.length if @traces
end