Class: NewRelic::Agent::ErrorTraceAggregator

Inherits:
Object
  • Object
show all
Defined in:
lib/new_relic/agent/error_trace_aggregator.rb

Instance Method Summary collapse

Constructor Details

#initialize(capacity) ⇒ ErrorTraceAggregator

Returns a new instance of ErrorTraceAggregator.



9
10
11
12
13
14
# File 'lib/new_relic/agent/error_trace_aggregator.rb', line 9

def initialize(capacity)
  @capacity = capacity
  @lock = Mutex.new
  @errors = []
  register_config_callbacks
end

Instance Method Details

#add_to_error_queue(noticed_error) ⇒ Object

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.



45
46
47
48
49
50
51
52
53
# File 'lib/new_relic/agent/error_trace_aggregator.rb', line 45

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?Boolean

Returns:

  • (Boolean)


16
17
18
# File 'lib/new_relic/agent/error_trace_aggregator.rb', line 16

def enabled?
  Agent.config[:'error_collector.enabled']
end

#harvest!Object

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



28
29
30
31
32
33
34
# File 'lib/new_relic/agent/error_trace_aggregator.rb', line 28

def harvest!
  @lock.synchronize do
    errors = @errors
    @errors = []
    errors
  end
end

#merge!(errors) ⇒ Object



20
21
22
23
24
# File 'lib/new_relic/agent/error_trace_aggregator.rb', line 20

def merge!(errors)
  errors.each do |error|
    add_to_error_queue(error)
  end
end

#notice_agent_error(exception) ⇒ Object

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



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/new_relic/agent/error_trace_aggregator.rb', line 74

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 }

    noticed_error = NewRelic::Agent.instance.error_collector.create_noticed_error(exception,
      {metric: 'NewRelic/AgentError'})
    noticed_error.stack_trace = caller.dup unless exception.backtrace

    @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) ⇒ Boolean

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.

Returns:

  • (Boolean)


57
58
59
60
61
62
63
# File 'lib/new_relic/agent/error_trace_aggregator.rb', line 57

def over_queue_limit?(message)
  over_limit = (@errors.count { |err| !err.is_internal } >= @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_callbacksObject



94
95
96
97
98
99
# File 'lib/new_relic/agent/error_trace_aggregator.rb', line 94

def register_config_callbacks
  Agent.config.register_callback(:'error_collector.enabled') do |enabled|
    reset! if enabled == false
    ::NewRelic::Agent.logger.debug("Error traces will #{enabled ? '' : 'not '}be sent to the New Relic service.")
  end
end

#reset!Object



36
37
38
39
40
# File 'lib/new_relic/agent/error_trace_aggregator.rb', line 36

def reset!
  @lock.synchronize do
    @errors = []
  end
end