airbrake-ruby 1.4.5 → 1.4.6
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 +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
|