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.
- checksums.yaml +7 -0
- data/lib/exceptionhandler.rb +113 -0
- metadata +84 -0
checksums.yaml
ADDED
|
@@ -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: []
|