Class: RightScale::ErrorTracker

Inherits:
Object
  • Object
show all
Includes:
RightSupport::Ruby::EasySingleton
Defined in:
lib/right_agent/error_tracker.rb

Overview

Tracker for unexpected errors Logs them with appropriate trace information Accumulates statistics about exceptions Reports exceptions to external Errbit service via HydraulicBrake

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#exception_statsObject (readonly)

Container for exception statistics



23
24
25
# File 'lib/right_agent/error_tracker.rb', line 23

def exception_stats
  @exception_stats
end

Instance Method Details

#init(agent, agent_name, options = {}) ⇒ TrueClass

Initialize error tracker

Parameters:

  • agent (Object)

    object using this tracker

  • agent_name (String)

    uniquely identifying agent process on given server

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :shard_id (Integer, NilClass)

    identifying shard of database in use

  • :trace_level (Hash)

    for restricting backtracing and Errbit reporting with exception class as key and :no_trace, :caller, or :trace as value; exceptions with :no_trace are not backtraced when logging nor are they recorded in stats or reported to Errbit

  • :airbrake_endpoint (String)

    URL for Airbrake for reporting exceptions to Errbit

  • :airbrake_api_key (String)

    for using the Airbrake API to access Errbit

Returns:

  • (TrueClass)

    always true



40
41
42
43
44
45
46
# File 'lib/right_agent/error_tracker.rb', line 40

def init(agent, agent_name, options = {})
  @agent = agent
  @trace_level = options[:trace_level] || {}
  notify_init(agent_name, options[:shard_id], options[:airbrake_endpoint], options[:airbrake_api_key])
  reset_stats
  true
end

#log(component, description, exception = nil, packet = nil, trace = nil) ⇒ Boolean

Log error and optionally track in stats Errbit notification is left to the callback configured in the stats tracker

Parameters:

  • component (String, Object)

    reporting error; non-string is snake-cased

  • description (String)

    of failure for use in logging

  • exception (Exception, String) (defaults to: nil)

    to be logged and tracked in stats; string errors are logged but not tracked in stats

  • packet (Packet, Hash, NilClass) (defaults to: nil)

    associated with exception

  • trace (Symbol, NilClass) (defaults to: nil)

    level override unless excluded by configured trace levels

Returns:

  • (Boolean)

    true if successfully logged, otherwise false



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/right_agent/error_tracker.rb', line 60

def log(component, description, exception = nil, packet = nil, trace = nil)
  if exception.nil?
    Log.error(description)
  elsif exception.is_a?(String)
    Log.error(description, exception)
  else
    trace = (@trace_level && @trace_level[exception.class]) || trace || :trace
    Log.error(description, exception, trace)
    track(component, exception, packet) if trace != :no_trace
  end
  true
rescue StandardError => e
  Log.error("Failed to log error", e, :trace) rescue nil
  false
end

#notify(exception, packet = nil, agent = nil, component = nil) ⇒ TrueClass

Notify Errbit of error if notification enabled

Parameters:

  • exception (Exception, String)

    raised

  • packet (Packet, Hash) (defaults to: nil)

    associated with exception

  • agent (Object) (defaults to: nil)

    object reporting error

  • component (String) (defaults to: nil)

    or service area where error occurred

Returns:

  • (TrueClass)

    always true



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/right_agent/error_tracker.rb', line 96

def notify(exception, packet = nil, agent = nil, component = nil)
  if @notify_enabled
    data = {
      :error_message => exception.respond_to?(:message) ? exception.message : exception.to_s,
      :backtrace => exception.respond_to?(:backtrace) ? exception.backtrace : caller,
      :environment_name => ENV["RAILS_ENV"],
    }
    if agent
      data[:cgi_data] = (@cgi_data || {}).merge(:agent_class => agent.class.name)
    elsif @cgi_data
      data[:cgi_data] = @cgi_data
    end
    data[:error_class] = exception.class.name if exception.is_a?(Exception)
    data[:component] = component if component
    if packet && packet.is_a?(Packet)
      data[:action] = packet.type.split("/").last if packet.respond_to?(:type)
      data[:parameters] = packet.payload if packet.respond_to?(:payload)
      uuid = packet.token if packet.respond_to?(:token)
    elsif packet.is_a?(Hash)
      action = packet[:path] || packet["path"]
      data[:action] = action.split("/").last if action
      data[:parameters] = packet[:data] || packet["data"]
      uuid = packet[:uuid] || packet["uuid"]
    end
    data[:session_data] = {:uuid => uuid} if uuid
    HydraulicBrake.notify(data)
  end
  true
rescue Exception => e
  Log.error("Failed to notify Errbit", e, :trace)
end

#notify_callbackProc

Create proc for making callback to notifier

Returns:

  • (Proc)

    notifier callback



131
132
133
134
135
# File 'lib/right_agent/error_tracker.rb', line 131

def notify_callback
  Proc.new do |exception, packet, agent, component|
    notify(exception, packet, agent, component)
  end
end

#stats(reset = false) ⇒ Hash

Get exception statistics

Parameters:

  • reset (Boolean) (defaults to: false)

    Whether to reset the statistics after getting the current ones

Returns:

  • (Hash)

    current statistics



142
143
144
145
146
# File 'lib/right_agent/error_tracker.rb', line 142

def stats(reset = false)
  stats = {"exceptions" => @exception_stats.all}
  reset_stats if reset
  stats
end

#track(component, exception, packet = nil) ⇒ TrueClass

Track error in stats

Parameters:

  • component (String)

    reporting error

  • exception (Exception)

    to be tracked

  • packet (Packet, Hash, NilClass) (defaults to: nil)

    associated with exception

Returns:

  • (TrueClass)

    always true



83
84
85
86
# File 'lib/right_agent/error_tracker.rb', line 83

def track(component, exception, packet = nil)
  component = component.class.name.split("::").last.snake_case unless component.is_a?(String)
  @exception_stats.track(component, exception, packet)
end