class NewRelic::Agent::ErrorTraceAggregator

Public Class Methods

new(capacity) click to toggle source
# File lib/new_relic/agent/error_trace_aggregator.rb, line 8
def initialize(capacity)
  @capacity = capacity
  @lock = Mutex.new
  @errors = []
  register_config_callbacks
end

Public Instance Methods

add_to_error_queue(noticed_error) click to toggle source

Synchronizes adding an error to the error queue, and checks if the error queue is too long - if so, we drop the error on the floor after logging a warning.

# File lib/new_relic/agent/error_trace_aggregator.rb, line 44
def add_to_error_queue(noticed_error)
  return unless enabled?
  @lock.synchronize do
    if !over_queue_limit?(noticed_error.message) && !@errors.include?(noticed_error)
      @errors << noticed_error
    end
  end
end
enabled?() click to toggle source
# File lib/new_relic/agent/error_trace_aggregator.rb, line 15
def enabled?
  Agent.config[:'error_collector.enabled']
end
harvest!() click to toggle source

Get the errors currently queued up. Unsent errors are left over from a previous unsuccessful attempt to send them to the server.

# File lib/new_relic/agent/error_trace_aggregator.rb, line 27
def harvest!
  @lock.synchronize do
    errors = @errors
    @errors = []
    errors
  end
end
merge!(errors) click to toggle source
# File lib/new_relic/agent/error_trace_aggregator.rb, line 19
def merge!(errors)
  errors.each do |error|
    add_to_error_queue(error)
  end
end
notice_agent_error(exception) click to toggle source

*Use sparingly for difficult to track bugs.*

Track internal agent errors for communication back to New Relic. To use, make a specific subclass of NewRelic::Agent::InternalAgentError, then pass an instance of it to this method when your problem occurs.

Limits are treated differently for these errors. We only gather one per class per harvest, disregarding (and not impacting) the app error queue limit.

# File lib/new_relic/agent/error_trace_aggregator.rb, line 72
def notice_agent_error(exception)
  return unless exception.class < NewRelic::Agent::InternalAgentError

  # Log 'em all!
  NewRelic::Agent.logger.info(exception)

  @lock.synchronize do
    # Already seen this class once? Bail!
    return if @errors.any? { |err| err.exception_class_name == exception.class.name }

    trace = exception.backtrace || caller.dup
    noticed_error = NewRelic::NoticedError.new("NewRelic/AgentError", exception)
    noticed_error.stack_trace = trace
    @errors << noticed_error
  end
rescue => e
  NewRelic::Agent.logger.info("Unable to capture internal agent error due to an exception:", e)
end
over_queue_limit?(message) click to toggle source

checks the size of the error queue to make sure we are under the maximum limit, and logs a warning if we are over the limit.

# File lib/new_relic/agent/error_trace_aggregator.rb, line 55
def over_queue_limit?(message)
  over_limit = (@errors.reject{|err| err.is_internal}.length >= @capacity)
  if over_limit
    ::NewRelic::Agent.logger.warn("The error reporting queue has reached #{@capacity}. The error detail for this and subsequent errors will not be transmitted to New Relic until the queued errors have been sent: #{message}")
  end
  over_limit
end
register_config_callbacks() click to toggle source
# File lib/new_relic/agent/error_trace_aggregator.rb, line 91
def register_config_callbacks
  Agent.config.register_callback(:'error_collector.enabled') do |enabled|
    ::NewRelic::Agent.logger.debug "Error traces will #{enabled ? '' : 'not '}be sent to the New Relic service."
  end
end
reset!() click to toggle source
# File lib/new_relic/agent/error_trace_aggregator.rb, line 35
def reset!
  @lock.synchronize do
    @errors = []
  end
end