exceptionhandler 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/exceptionhandler.rb +113 -0
  3. metadata +84 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 692e4a01778c53380866d74732449d718f662745
4
+ data.tar.gz: 2e4499d00e7297f06907b7843c4ddf5ddcb184a8
5
+ SHA512:
6
+ metadata.gz: 4a2f46721280c3c7ba3f7c4a60bced301387da991770714072f13a38aa823b0af52294dd625d52a98fd01ef1bbb7848f73489db43ce4ba0f2ed96370440e8741
7
+ data.tar.gz: f339a472ad74f9e275fa94c36e425cbcb0300fd47459221770e6c0b8dfe859cb631dee4feea81740878fd1d8bb9c5faf94ab55d08c29bb140eaefd698091ff21
@@ -0,0 +1,113 @@
1
+ require 'logger'
2
+ require 'unirest'
3
+ require 'httpclient'
4
+
5
+
6
+ class ExceptionHandler
7
+
8
+ def initialize()
9
+ #Get the cluster name from Google metadata service
10
+ cluster_name="unknown_cluster"
11
+ begin
12
+ response = Unirest.get('http://metadata.google.internal/computeMetadata/v1/instance/attributes/cluster-name',headers:{ "Metadata-Flavor" => "Google"})
13
+ if response.code == 200
14
+ cluster_name=response.body
15
+ end
16
+ rescue
17
+ p "Couldn't determine cluster name."
18
+ end
19
+
20
+ #Grap the rest of the details from tags
21
+ environment = ENV['environment'] ? ENV['environment'] : "unknown_env"
22
+ app = ENV['DEIS_APP'] ? ENV['DEIS_APP'] : "unknown_app"
23
+ release = ENV['WORKFLOW_RELEASE'] ? ENV['WORKFLOW_RELEASE'] : "unknown_release"
24
+
25
+ @request_body_base = {:application => app, :version => release, :environment => environment, :cluster => cluster_name, :token => ENV['EXCEPTION_TOKEN']}
26
+ end
27
+
28
+ def call(options)
29
+ if !options[:exception].nil?
30
+
31
+ trace_chain = trace_chain(options[:exception])
32
+ puts "Exception Caught ("+options[:exception].class.name+"): " + trace_chain.to_s
33
+
34
+ excep = options[:exception].class.name
35
+ backtrace = "#{ options[:exception].message } (#{ options[:exception].class })\n" <<
36
+ (options[:exception].backtrace || []).join("\n")
37
+
38
+ if ENV['EXCEPTION_URL']
39
+ excep = options[:exception].class.name
40
+ backtrace = "#{ options[:exception].message } (#{ options[:exception].class })\n" <<
41
+ (options[:exception].backtrace || []).join("\n")
42
+
43
+ # Create a hash id from the exception class and the stacktrace to identify unique occurences of the same exception class
44
+ hash_id = Digest::SHA256.hexdigest "#{options[:exception].class} #{options[:exception].backtrace}"
45
+
46
+ request_body = @request_body_base
47
+ request_body[:timestamp] = Time.now
48
+ request_body[:id] = hash_id
49
+ request_body[:exception] = excep
50
+ request_body[:detail] = backtrace
51
+
52
+ clnt = HTTPClient.new()
53
+ clnt.post_async("#{ENV['EXCEPTION_URL']}/exception", request_body)
54
+ end
55
+
56
+ else
57
+ puts options
58
+ end
59
+
60
+ #The whole point of this handler is to replace rollbar, so raise this exception to prevent trying to send to rollbar
61
+ raise Rollbar::Ignore
62
+ end
63
+
64
+
65
+ def trace_chain(exception)
66
+ traces = [trace_data(exception)]
67
+ visited = [exception]
68
+ current_exception = exception
69
+
70
+ while current_exception.respond_to?(:cause) && (cause = current_exception.cause) && cause.is_a?(Exception) && !visited.include?(cause)
71
+ traces << trace_data(cause)
72
+ visited << cause
73
+ current_exception = cause
74
+ end
75
+
76
+ traces
77
+ end
78
+
79
+ def trace_data(current_exception)
80
+ frames = reduce_frames(current_exception)
81
+ # reverse so that the order is as rollbar expects
82
+ frames.reverse!
83
+
84
+ {
85
+ :frames => frames,
86
+ :exception => {
87
+ :class => current_exception.class.name,
88
+ :message => current_exception.message
89
+ }
90
+ }
91
+ end
92
+
93
+ def reduce_frames(current_exception)
94
+ exception_backtrace(current_exception).map do |frame|
95
+ # parse the line
96
+ match = frame.match(/(.*):(\d+)(?::in `([^']+)')?/)
97
+
98
+ if match
99
+ { :filename => match[1], :lineno => match[2].to_i, :method => match[3] }
100
+ else
101
+ { :filename => '<unknown>', :lineno => 0, :method => frame }
102
+ end
103
+ end
104
+ end
105
+
106
+ def exception_backtrace(current_exception)
107
+ return [] if current_exception.nil?
108
+ return current_exception.backtrace if current_exception.backtrace.respond_to?(:map)
109
+ return []
110
+ end
111
+
112
+
113
+ end
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: exceptionhandler
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Matt Knox
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-06-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httpclient
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.8'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.8.2.2
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '2.8'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.8.2.2
33
+ - !ruby/object:Gem::Dependency
34
+ name: unirest
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.1'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 1.1.2
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '1.1'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 1.1.2
53
+ description: Log exceptions in a log friendly way.
54
+ email: matt.knox@sphero.com
55
+ executables: []
56
+ extensions: []
57
+ extra_rdoc_files: []
58
+ files:
59
+ - lib/exceptionhandler.rb
60
+ homepage:
61
+ licenses:
62
+ - MIT
63
+ metadata: {}
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubyforge_project:
80
+ rubygems_version: 2.5.1
81
+ signing_key:
82
+ specification_version: 4
83
+ summary: Log exceptions in a log friendly way.
84
+ test_files: []