airbrake-ruby 1.4.5 → 1.4.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/airbrake-ruby.rb +5 -0
- data/lib/airbrake-ruby/backtrace.rb +92 -74
- data/lib/airbrake-ruby/version.rb +1 -1
- data/spec/backtrace_spec.rb +30 -8
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e55d1ef72a4b324c33893e56abd9e92c661461c
|
4
|
+
data.tar.gz: 14b98e0a8ba23394efd7c967add4ce0bdc93042c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 33b3db9de069c13caf56f7b63b423e4ef83730b6f40398e251e9bd075d043d5b1aada097884748394d315af95e76274841e616a610dfe3f99d8cb93eed22f83f
|
7
|
+
data.tar.gz: 5f99f46b2ad687d9f9b3a11505c8189620a2f18ac63f4bb7fe5436c7b9aa88b3880f7adb0ca8f88edee299d92619e410c31f2915bff5861d3148551253c339eb
|
data/lib/airbrake-ruby.rb
CHANGED
@@ -63,6 +63,11 @@ module Airbrake
|
|
63
63
|
# @return [String] the label to be prepended to the log output
|
64
64
|
LOG_LABEL = '**Airbrake:'.freeze
|
65
65
|
|
66
|
+
##
|
67
|
+
# @return [Boolean] true if current Ruby is Ruby 1.9.*. The result is used
|
68
|
+
# for special cases where we need to work around older implementations
|
69
|
+
RUBY_19 = RUBY_VERSION.start_with?('1.9')
|
70
|
+
|
66
71
|
##
|
67
72
|
# A Hash that holds all notifiers. The keys of the Hash are notifier
|
68
73
|
# names, the values are Airbrake::Notifier instances.
|
@@ -11,74 +11,81 @@ module Airbrake
|
|
11
11
|
# Backtrace.parse($!, Logger.new(STDOUT))
|
12
12
|
# end
|
13
13
|
module Backtrace
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
14
|
+
module Patterns
|
15
|
+
##
|
16
|
+
# @return [Regexp] the pattern that matches standard Ruby stack frames,
|
17
|
+
# such as ./spec/notice_spec.rb:43:in `block (3 levels) in <top (required)>'
|
18
|
+
RUBY = %r{\A
|
19
|
+
(?<file>.+) # Matches './spec/notice_spec.rb'
|
20
|
+
:
|
21
|
+
(?<line>\d+) # Matches '43'
|
22
|
+
:in\s
|
23
|
+
`(?<function>.*)' # Matches "`block (3 levels) in <top (required)>'"
|
24
|
+
\z}x
|
25
|
+
|
26
|
+
##
|
27
|
+
# @return [Regexp] the pattern that matches JRuby Java stack frames, such
|
28
|
+
# as org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
|
29
|
+
JAVA = /\A
|
30
|
+
(?<function>.+) # Matches 'org.jruby.ast.NewlineNode.interpret
|
31
|
+
\(
|
32
|
+
(?<file>[^:]+) # Matches 'NewlineNode.java'
|
33
|
+
:?
|
34
|
+
(?<line>\d+)? # Matches '105'
|
35
|
+
\)
|
36
|
+
\z/x
|
37
|
+
|
38
|
+
##
|
39
|
+
# @return [Regexp] the pattern that tries to assume what a generic stack
|
40
|
+
# frame might look like, when exception's backtrace is set manually.
|
41
|
+
GENERIC = %r{\A
|
42
|
+
(?:from\s)?
|
43
|
+
(?<file>.+) # Matches '/foo/bar/baz.ext'
|
44
|
+
:
|
45
|
+
(?<line>\d+)? # Matches '43' or nothing
|
46
|
+
(?:
|
47
|
+
in\s`(?<function>.+)' # Matches "in `func'"
|
48
|
+
|
|
49
|
+
:in\s(?<function>.+) # Matches ":in func"
|
50
|
+
)? # ... or nothing
|
51
|
+
\z}x
|
52
|
+
|
53
|
+
##
|
54
|
+
# @return [Regexp] the pattern that matches exceptions from PL/SQL such as
|
55
|
+
# ORA-06512: at "STORE.LI_LICENSES_PACK", line 1945
|
56
|
+
# @note This is raised by https://github.com/kubo/ruby-oci8
|
57
|
+
OCI = /\A
|
58
|
+
(?:
|
59
|
+
ORA-\d{5}
|
60
|
+
:\sat\s
|
61
|
+
(?:"(?<function>.+)",\s)?
|
62
|
+
line\s(?<line>\d+)
|
63
|
+
|
|
64
|
+
#{GENERIC}
|
65
|
+
)
|
66
|
+
\z/x
|
67
|
+
|
68
|
+
##
|
69
|
+
# @return [Regexp] the pattern that matches CoffeeScript backtraces
|
70
|
+
# usually coming from Rails & ExecJS
|
71
|
+
EXECJS = /\A
|
72
|
+
(?:
|
73
|
+
# Matches 'compile ((execjs):6692:19)'
|
74
|
+
(?<function>.+)\s\((?<file>.+):(?<line>\d+):\d+\)
|
75
|
+
|
|
76
|
+
# Matches 'bootstrap_node.js:467:3'
|
77
|
+
(?<file>.+):(?<line>\d+):\d+(?<function>)
|
78
|
+
|
|
79
|
+
# Matches the Ruby part of the backtrace
|
80
|
+
#{RUBY}
|
81
|
+
)
|
82
|
+
\z/x
|
83
|
+
|
84
|
+
##
|
85
|
+
# @return [Regexp] +EXECJS+ pattern without named captures and
|
86
|
+
# uncommon frames
|
87
|
+
EXECJS_SIMPLIFIED = /\A.+ \(.+:\d+:\d+\)\z/
|
88
|
+
end
|
82
89
|
|
83
90
|
##
|
84
91
|
# Parses an exception's backtrace.
|
@@ -121,13 +128,13 @@ module Airbrake
|
|
121
128
|
|
122
129
|
def best_regexp_for(exception)
|
123
130
|
if java_exception?(exception)
|
124
|
-
|
131
|
+
Patterns::JAVA
|
125
132
|
elsif oci_exception?(exception)
|
126
|
-
|
133
|
+
Patterns::OCI
|
127
134
|
elsif execjs_exception?(exception)
|
128
|
-
|
135
|
+
Patterns::EXECJS
|
129
136
|
else
|
130
|
-
|
137
|
+
Patterns::RUBY
|
131
138
|
end
|
132
139
|
end
|
133
140
|
|
@@ -135,13 +142,24 @@ module Airbrake
|
|
135
142
|
defined?(OCIError) && exception.is_a?(OCIError)
|
136
143
|
end
|
137
144
|
|
145
|
+
# rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
138
146
|
def execjs_exception?(exception)
|
139
147
|
return false unless defined?(ExecJS::RuntimeError)
|
140
148
|
return true if exception.is_a?(ExecJS::RuntimeError)
|
141
|
-
|
149
|
+
|
150
|
+
if Airbrake::RUBY_19
|
151
|
+
# Ruby 1.9 doesn't support Exception#cause. We work around this by
|
152
|
+
# parsing backtraces. It's slow, so we check only a few first frames.
|
153
|
+
exception.backtrace[0..2].each do |frame|
|
154
|
+
return true if frame =~ Patterns::EXECJS_SIMPLIFIED
|
155
|
+
end
|
156
|
+
elsif exception.cause && exception.cause.is_a?(ExecJS::RuntimeError)
|
157
|
+
return true
|
158
|
+
end
|
142
159
|
|
143
160
|
false
|
144
161
|
end
|
162
|
+
# rubocop:enable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
145
163
|
|
146
164
|
def stack_frame(match)
|
147
165
|
{ file: match[:file],
|
@@ -153,7 +171,7 @@ module Airbrake
|
|
153
171
|
match = regexp.match(stackframe)
|
154
172
|
return match if match
|
155
173
|
|
156
|
-
|
174
|
+
Patterns::GENERIC.match(stackframe)
|
157
175
|
end
|
158
176
|
end
|
159
177
|
end
|
data/spec/backtrace_spec.rb
CHANGED
@@ -191,7 +191,7 @@ RSpec.describe Airbrake::Backtrace do
|
|
191
191
|
end
|
192
192
|
end
|
193
193
|
|
194
|
-
context "given an ExecJS
|
194
|
+
context "given an ExecJS exception" do
|
195
195
|
let(:bt) do
|
196
196
|
['compile ((execjs):6692:19)',
|
197
197
|
'eval (<anonymous>:1:10)',
|
@@ -203,8 +203,6 @@ RSpec.describe Airbrake::Backtrace do
|
|
203
203
|
"/opt/rubies/ruby-2.3.1/lib/ruby/2.3.0/benchmark.rb:308:in `realtime'"]
|
204
204
|
end
|
205
205
|
|
206
|
-
let(:ex) { ExecJS::RuntimeError.new.tap { |e| e.set_backtrace(bt) } }
|
207
|
-
|
208
206
|
let(:parsed_backtrace) do
|
209
207
|
[{ file: '(execjs)', line: 6692, function: 'compile' },
|
210
208
|
{ file: '<anonymous>', line: 1, function: 'eval' },
|
@@ -218,11 +216,35 @@ RSpec.describe Airbrake::Backtrace do
|
|
218
216
|
function: 'realtime' }]
|
219
217
|
end
|
220
218
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
219
|
+
context "when not on Ruby 1.9" do
|
220
|
+
let(:ex) { ExecJS::RuntimeError.new.tap { |e| e.set_backtrace(bt) } }
|
221
|
+
|
222
|
+
it "returns a properly formatted array of hashes" do
|
223
|
+
stub_const('ExecJS::RuntimeError', AirbrakeTestError)
|
224
|
+
stub_const('Airbrake::RUBY_19', false)
|
225
|
+
|
226
|
+
expect(
|
227
|
+
described_class.parse(ex, Logger.new('/dev/null'))
|
228
|
+
).to eq(parsed_backtrace)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
context "when on Ruby 1.9" do
|
233
|
+
context "and when exception's class isn't ExecJS" do
|
234
|
+
let(:ex) do
|
235
|
+
ActionView::Template::Error.new.tap { |e| e.set_backtrace(bt) }
|
236
|
+
end
|
237
|
+
|
238
|
+
it "returns a properly formatted array of hashes" do
|
239
|
+
stub_const('ActionView::Template::Error', AirbrakeTestError)
|
240
|
+
stub_const('ExecJS::RuntimeError', NameError)
|
241
|
+
stub_const('Airbrake::RUBY_19', true)
|
242
|
+
|
243
|
+
expect(
|
244
|
+
described_class.parse(ex, Logger.new('/dev/null'))
|
245
|
+
).to eq(parsed_backtrace)
|
246
|
+
end
|
247
|
+
end
|
226
248
|
end
|
227
249
|
end
|
228
250
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: airbrake-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.4.
|
4
|
+
version: 1.4.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Airbrake Technologies, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-08-
|
11
|
+
date: 2016-08-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|