exceptionhandler 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []