lib/new_relic/agent/agent.rb in newrelic_rpm-3.0.1 vs lib/new_relic/agent/agent.rb in newrelic_rpm-3.1.0.beta1
- old
+ new
@@ -62,10 +62,22 @@
attr_reader :histogram
attr_reader :metric_ids
attr_reader :url_rules
attr_reader :beacon_configuration
+ def unsent_errors_size
+ @unsent_errors.length if @unsent_errors
+ end
+
+ def unsent_traces_size
+ @traces.length if @traces
+ end
+
+ def unsent_timeslice_data
+ @unsent_timeslice_data.keys.length
+ end
+
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
@@ -148,13 +160,15 @@
def connected?
@connected
end
# Attempt a graceful shutdown of the agent.
- def shutdown
+ 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
@@ -429,12 +443,13 @@
end
def create_and_run_worker_loop
@worker_loop = WorkerLoop.new
@worker_loop.run(@report_period) do
- harvest_and_send_slowest_sample if @should_send_samples
- harvest_and_send_errors if error_collector.enabled
+ NewRelic::Agent.load_data
+ harvest_and_send_errors
+ harvest_and_send_slowest_sample
harvest_and_send_timeslice_data
end
end
def handle_force_restart(error)
@@ -660,10 +675,41 @@
log.debug "Connection data = #{config_data.inspect}"
end
end
include Connect
+ def serialize
+ accumulator = []
+ accumulator[1] = harvest_transaction_traces if @transaction_sampler
+ accumulator[2] = harvest_errors if @error_collector
+ accumulator[0] = harvest_timeslice_data
+ accumulator
+ end
+
+ public :serialize
+
+ 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
+
+ public :merge_data_from
+
# Connect to the server and validate the license. If successful,
# @connected has true when finished. If not successful, you can
# keep calling this. Return false if we could not establish a
# connection with the server and we should not retry, such as if
# there's a bad license key.
@@ -713,36 +759,43 @@
def is_application_spawner?
$0 =~ /ApplicationSpawner|^unicorn\S* master/
end
- def harvest_and_send_timeslice_data
-
+ def harvest_timeslice_data(time=Time.now)
+ # this creates timeslices that are harvested below
NewRelic::Agent::BusyCalculator.harvest_busy
- now = Time.now
- NewRelic::Agent.instance.stats_engine.get_stats_no_scope('Supportability/invoke_remote').record_data_point(0.0)
- NewRelic::Agent.instance.stats_engine.get_stats_no_scope('Supportability/invoke_remote/metric_data').record_data_point(0.0)
-
@unsent_timeslice_data ||= {}
@unsent_timeslice_data = @stats_engine.harvest_timeslice_data(@unsent_timeslice_data, @metric_ids)
+ @unsent_timeslice_data
+ end
+ def fill_metric_id_cache(pairs_of_specs_and_ids)
+ Array(pairs_of_specs_and_ids).each do |metric_spec, metric_id|
+ @metric_ids[metric_spec] = metric_id
+ end
+ end
+
+ def harvest_and_send_timeslice_data
+ now = Time.now
+ NewRelic::Agent.instance.stats_engine.get_stats_no_scope('Supportability/invoke_remote').record_data_point(0.0)
+ NewRelic::Agent.instance.stats_engine.get_stats_no_scope('Supportability/invoke_remote/metric_data').record_data_point(0.0)
+ harvest_timeslice_data(now)
begin
# In this version of the protocol, we get back an assoc array of spec to id.
- metric_ids = invoke_remote(:metric_data, @agent_id,
+ metric_specs_and_ids = invoke_remote(:metric_data, @agent_id,
@last_harvest_time.to_f,
now.to_f,
@unsent_timeslice_data.values)
rescue Timeout::Error
# assume that the data was received. chances are that it was
- metric_ids = nil
+ metric_specs_and_ids = []
end
- metric_ids.each do | spec, id |
- @metric_ids[spec] = id
- end if metric_ids
+ fill_metric_id_cache(metric_specs_and_ids)
log.debug "#{now}: sent #{@unsent_timeslice_data.length} timeslices (#{@agent_id}) in #{Time.now - now} seconds"
# if we successfully invoked this web service, then clear the unsent message cache.
@unsent_timeslice_data = {}
@@ -752,13 +805,17 @@
# note - exceptions are logged in invoke_remote. If an exception is encountered here,
# then the metric data is downsampled for another timeslices
end
- def harvest_and_send_slowest_sample
+ def harvest_transaction_traces
@traces = @transaction_sampler.harvest(@traces, @slowest_transaction_threshold)
+ @traces
+ end
+ def harvest_and_send_slowest_sample
+ harvest_transaction_traces
unless @traces.empty?
now = Time.now
log.debug "Sending (#{@traces.length}) transaction traces"
begin
# take the traces and prepare them for sending across the
@@ -790,12 +847,17 @@
# exception is encountered here, then the slowest sample of is
# determined of the entire period since the last reported
# sample.
end
- def harvest_and_send_errors
+ def harvest_errors
@unsent_errors = @error_collector.harvest_errors(@unsent_errors)
+ @unsent_errors
+ end
+
+ def harvest_and_send_errors
+ harvest_errors
if @unsent_errors && @unsent_errors.length > 0
log.debug "Sending #{@unsent_errors.length} errors"
begin
invoke_remote :error_data, @agent_id, @unsent_errors
rescue PostTooBigException
@@ -923,18 +985,20 @@
rescue SystemCallError, SocketError => e
# These include Errno connection errors
raise NewRelic::Agent::ServerConnectionException, "Recoverable error connecting to the server: #{e}"
ensure
NewRelic::Agent.instance.stats_engine.get_stats_no_scope('Supportability/invoke_remote').record_data_point((Time.now - now).to_f)
- NewRelic::Agent.instance.stats_engine.get_stats_no_scope('Supportability/invoke_remote/' + method.to_s).record_data_point((Time.now - now).to_f)
+ NewRelic::Agent.instance.stats_engine.get_stats_no_scope('Supportability/invoke_remote/' + method.to_s).record_data_point((Time.now - now).to_f)
end
def graceful_disconnect
if @connected
begin
@request_timeout = 10
- log.debug "Flushing unsent metric data to server"
- @worker_loop.run_task
+# log.debug "Flushing unsent metric data to server"
+# harvest_and_send_timeslice_data
+ log.debug "Serializing agent data to disk"
+ NewRelic::Agent.save_data
if @connected_pid == $$
log.debug "Sending RPM service agent run shutdown message"
invoke_remote :shutdown, @agent_id, Time.now.to_f
else
log.debug "This agent connected from parent process #{@connected_pid}--not sending shutdown"