Class: ExceptionHandler

Inherits:
Object
  • Object
show all
Defined in:
lib/exceptionhandler.rb

Instance Method Summary collapse

Constructor Details

#initializeExceptionHandler

Returns a new instance of ExceptionHandler.



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/exceptionhandler.rb', line 7

def initialize()
  #Get the cluster name from Google metadata service
  cluster_name="unknown_cluster"
  begin
    clnt = HTTPClient.new()
    response = clnt.get "http://metadata.google.internal/computeMetadata/v1/instance/attributes/cluster-name", nil, "Metadata-Flavor" => "Google"
    if response.status == 200
      cluster_name=response.body
    end
  rescue
    p "Couldn't determine cluster name."
  end

  #Grap the rest of the details from tags
  environment = ENV['environment'] ? ENV['environment'] : "unknown_env"
  app = ENV['DEIS_APP'] ? ENV['DEIS_APP'] : "unknown_app"
  release = ENV['WORKFLOW_RELEASE'] ? ENV['WORKFLOW_RELEASE'] : "unknown_release"

  @request_body_base = {:application => app, :version => release, :environment => environment, :cluster => cluster_name, :token => ENV['EXCEPTION_TOKEN']}
end

Instance Method Details

#call(options) ⇒ Object

Raises:

  • (Rollbar::Ignore)


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/exceptionhandler.rb', line 28

def call(options)
  if !options[:exception].nil?

    trace_chain = trace_chain(options[:exception])
    puts "Exception Caught ("+options[:exception].class.name+"): " + trace_chain.to_s

    excep = options[:exception].class.name 
    backtrace = "#{ options[:exception].message } (#{ options[:exception].class })\n" <<
    (options[:exception].backtrace || []).join("\n")

    if ENV['EXCEPTION_URL']
      excep = options[:exception].class.name
      backtrace = "#{ options[:exception].message } (#{ options[:exception].class })\n" <<
      (options[:exception].backtrace || []).join("\n")

      # Create a hash id from the exception class and the stacktrace to identify unique occurences of the same exception class
      hash_id = Digest::SHA256.hexdigest "#{excep} #{backtrace}"

      request_body = @request_body_base
      request_body[:timestamp] = Time.now
      request_body[:id] = hash_id
      request_body[:exception] = excep
      request_body[:detail] = backtrace

      clnt = HTTPClient.new()
      clnt.post_async("#{ENV['EXCEPTION_URL']}/exception", request_body) 
    end

  else
    puts options
  end
  
  #The whole point of this handler is to replace rollbar, so raise this exception to prevent trying to send to rollbar
  raise Rollbar::Ignore
end

#exception_backtrace(current_exception) ⇒ Object



106
107
108
109
110
# File 'lib/exceptionhandler.rb', line 106

def exception_backtrace(current_exception)
      return [] if current_exception.nil?
      return current_exception.backtrace if current_exception.backtrace.respond_to?(:map)
      return []
end

#reduce_frames(current_exception) ⇒ Object



93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/exceptionhandler.rb', line 93

def reduce_frames(current_exception)
  exception_backtrace(current_exception).map do |frame|
    # parse the line
    match = frame.match(/(.*):(\d+)(?::in `([^']+)')?/)

    if match
      { :filename => match[1], :lineno => match[2].to_i, :method => match[3] }
    else
      { :filename => '<unknown>', :lineno => 0, :method => frame }
    end
  end
end

#trace_chain(exception) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/exceptionhandler.rb', line 65

def trace_chain(exception)
  traces = [trace_data(exception)]
  visited = [exception]
  current_exception = exception

  while current_exception.respond_to?(:cause) && (cause = current_exception.cause) && cause.is_a?(Exception) && !visited.include?(cause)
    traces << trace_data(cause)
    visited << cause
    current_exception = cause
  end

  traces
end

#trace_data(current_exception) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/exceptionhandler.rb', line 79

def trace_data(current_exception)
  frames = reduce_frames(current_exception)
  # reverse so that the order is as rollbar expects
  frames.reverse!

  {
    :frames => frames,
    :exception => {
      :class => current_exception.class.name,
      :message => current_exception.message
    }
  }
end