airbrake-ruby 1.4.3 → 1.4.4
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/backtrace.rb +41 -8
- data/lib/airbrake-ruby/nested_exception.rb +3 -2
- data/lib/airbrake-ruby/notice.rb +1 -1
- data/lib/airbrake-ruby/version.rb +1 -1
- data/spec/backtrace_spec.rb +57 -13
- data/spec/nested_exception_spec.rb +3 -3
- 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: eaad02409926687bb224ce9b635ba755d70ae2ca
|
4
|
+
data.tar.gz: 4cf429a9c5cfc4f440ee674ab8c06105447e08a2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ad0da44bc123bb6c14387d14772796bfefdbbdf8f143285ba839867051771939faf3a2d9ff328f5f3f89231b4a0c7560038eec45601731ec8e6d32d9bd05530
|
7
|
+
data.tar.gz: 26199fd126b11a6ea0a7449ff41591760ffd9642b8eef9c20f7f0e3cb041acb13ba0d1be70d40526a470458374896f086dd3b0c4a7cff657204eb189a02cb165
|
@@ -8,7 +8,7 @@ module Airbrake
|
|
8
8
|
# begin
|
9
9
|
# raise 'Oops!'
|
10
10
|
# rescue
|
11
|
-
# Backtrace.parse(
|
11
|
+
# Backtrace.parse($!, Logger.new(STDOUT))
|
12
12
|
# end
|
13
13
|
module Backtrace
|
14
14
|
##
|
@@ -38,29 +38,61 @@ module Airbrake
|
|
38
38
|
# @return [Regexp] the template that tries to assume what a generic stack
|
39
39
|
# frame might look like, when exception's backtrace is set manually.
|
40
40
|
GENERIC_STACKFRAME_REGEXP = %r{\A
|
41
|
+
(?:from\s)?
|
41
42
|
(?<file>.+) # Matches '/foo/bar/baz.ext'
|
42
43
|
:
|
43
44
|
(?<line>\d+)? # Matches '43' or nothing
|
44
|
-
(
|
45
|
+
(?:
|
46
|
+
in\s`(?<function>.+)' # Matches "in `func'"
|
47
|
+
|
|
48
|
+
:in\s(?<function>.+) # Matches ":in func"
|
49
|
+
)? # ... or nothing
|
45
50
|
\z}x
|
46
51
|
|
52
|
+
##
|
53
|
+
# @return [Regexp] the template that matches exceptions from PL/SQL such as
|
54
|
+
# ORA-06512: at "STORE.LI_LICENSES_PACK", line 1945
|
55
|
+
# @note This is raised by https://github.com/kubo/ruby-oci8
|
56
|
+
OCI_STACKFRAME_REGEXP = /\A
|
57
|
+
(?:
|
58
|
+
ORA-\d{5}
|
59
|
+
:\sat\s
|
60
|
+
(?:"(?<function>.+)",\s)?
|
61
|
+
line\s(?<line>\d+)
|
62
|
+
|
|
63
|
+
#{GENERIC_STACKFRAME_REGEXP}
|
64
|
+
)
|
65
|
+
\z/x
|
66
|
+
|
47
67
|
##
|
48
68
|
# Parses an exception's backtrace.
|
49
69
|
#
|
50
70
|
# @param [Exception] exception The exception, which contains a backtrace to
|
51
71
|
# parse
|
52
72
|
# @return [Array<Hash{Symbol=>String,Integer}>] the parsed backtrace
|
53
|
-
def self.parse(exception)
|
73
|
+
def self.parse(exception, logger)
|
54
74
|
return [] if exception.backtrace.nil? || exception.backtrace.none?
|
55
75
|
|
56
76
|
regexp = if java_exception?(exception)
|
57
77
|
JAVA_STACKFRAME_REGEXP
|
78
|
+
elsif oci_exception?(exception)
|
79
|
+
OCI_STACKFRAME_REGEXP
|
58
80
|
else
|
59
81
|
RUBY_STACKFRAME_REGEXP
|
60
82
|
end
|
61
83
|
|
62
84
|
exception.backtrace.map do |stackframe|
|
63
|
-
|
85
|
+
frame = match_frame(regexp, stackframe)
|
86
|
+
|
87
|
+
unless frame
|
88
|
+
logger.error(
|
89
|
+
"can't parse '#{stackframe}' (please file an issue so we can fix " \
|
90
|
+
"it: https://github.com/airbrake/airbrake-ruby/issues/new)"
|
91
|
+
)
|
92
|
+
frame = { file: nil, line: nil, function: stackframe }
|
93
|
+
end
|
94
|
+
|
95
|
+
stack_frame(frame)
|
64
96
|
end
|
65
97
|
end
|
66
98
|
|
@@ -77,6 +109,10 @@ module Airbrake
|
|
77
109
|
class << self
|
78
110
|
private
|
79
111
|
|
112
|
+
def oci_exception?(exception)
|
113
|
+
defined?(OCIError) && exception.is_a?(OCIError)
|
114
|
+
end
|
115
|
+
|
80
116
|
def stack_frame(match)
|
81
117
|
{ file: match[:file],
|
82
118
|
line: (Integer(match[:line]) if match[:line]),
|
@@ -87,10 +123,7 @@ module Airbrake
|
|
87
123
|
match = regexp.match(stackframe)
|
88
124
|
return match if match
|
89
125
|
|
90
|
-
|
91
|
-
return match if match
|
92
|
-
|
93
|
-
raise Airbrake::Error, "can't parse '#{stackframe}'"
|
126
|
+
GENERIC_STACKFRAME_REGEXP.match(stackframe)
|
94
127
|
end
|
95
128
|
end
|
96
129
|
end
|
@@ -8,15 +8,16 @@ module Airbrake
|
|
8
8
|
# can unwrap. Exceptions that have a longer cause chain will be ignored
|
9
9
|
MAX_NESTED_EXCEPTIONS = 3
|
10
10
|
|
11
|
-
def initialize(exception)
|
11
|
+
def initialize(exception, logger)
|
12
12
|
@exception = exception
|
13
|
+
@logger = logger
|
13
14
|
end
|
14
15
|
|
15
16
|
def as_json
|
16
17
|
unwind_exceptions.map do |exception|
|
17
18
|
{ type: exception.class.name,
|
18
19
|
message: exception.message,
|
19
|
-
backtrace: Backtrace.parse(exception) }
|
20
|
+
backtrace: Backtrace.parse(exception, @logger) }
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
data/lib/airbrake-ruby/notice.rb
CHANGED
data/spec/backtrace_spec.rb
CHANGED
@@ -3,8 +3,6 @@ require 'spec_helper'
|
|
3
3
|
RSpec.describe Airbrake::Backtrace do
|
4
4
|
describe ".parse" do
|
5
5
|
context "UNIX backtrace" do
|
6
|
-
let(:backtrace) { described_class.new(AirbrakeTestError.new) }
|
7
|
-
|
8
6
|
let(:parsed_backtrace) do
|
9
7
|
# rubocop:disable Metrics/LineLength, Style/HashSyntax, Style/SpaceAroundOperators, Style/SpaceInsideHashLiteralBraces
|
10
8
|
[{:file=>"/home/kyrylo/code/airbrake/ruby/spec/spec_helper.rb", :line=>23, :function=>"<top (required)>"},
|
@@ -24,8 +22,9 @@ RSpec.describe Airbrake::Backtrace do
|
|
24
22
|
end
|
25
23
|
|
26
24
|
it "returns a properly formatted array of hashes" do
|
27
|
-
expect(
|
28
|
-
|
25
|
+
expect(
|
26
|
+
described_class.parse(AirbrakeTestError.new, Logger.new('/dev/null'))
|
27
|
+
).to eq(parsed_backtrace)
|
29
28
|
end
|
30
29
|
end
|
31
30
|
|
@@ -45,7 +44,9 @@ RSpec.describe Airbrake::Backtrace do
|
|
45
44
|
end
|
46
45
|
|
47
46
|
it "returns a properly formatted array of hashes" do
|
48
|
-
expect(
|
47
|
+
expect(
|
48
|
+
described_class.parse(ex, Logger.new('/dev/null'))
|
49
|
+
).to eq(parsed_backtrace)
|
49
50
|
end
|
50
51
|
end
|
51
52
|
|
@@ -69,8 +70,9 @@ RSpec.describe Airbrake::Backtrace do
|
|
69
70
|
it "returns a properly formatted array of hashes" do
|
70
71
|
allow(described_class).to receive(:java_exception?).and_return(true)
|
71
72
|
|
72
|
-
expect(
|
73
|
-
|
73
|
+
expect(
|
74
|
+
described_class.parse(JavaAirbrakeTestError.new, Logger.new('/dev/null'))
|
75
|
+
).to eq(backtrace_array)
|
74
76
|
end
|
75
77
|
end
|
76
78
|
|
@@ -95,7 +97,9 @@ RSpec.describe Airbrake::Backtrace do
|
|
95
97
|
end
|
96
98
|
|
97
99
|
it "returns a properly formatted array of hashes" do
|
98
|
-
expect(
|
100
|
+
expect(
|
101
|
+
described_class.parse(ex, Logger.new('/dev/null'))
|
102
|
+
).to eq(parsed_backtrace)
|
99
103
|
end
|
100
104
|
end
|
101
105
|
|
@@ -113,7 +117,9 @@ RSpec.describe Airbrake::Backtrace do
|
|
113
117
|
end
|
114
118
|
|
115
119
|
it "returns a properly formatted array of hashes" do
|
116
|
-
expect(
|
120
|
+
expect(
|
121
|
+
described_class.parse(ex, Logger.new('/dev/null'))
|
122
|
+
).to eq(parsed_backtrace)
|
117
123
|
end
|
118
124
|
end
|
119
125
|
end
|
@@ -123,9 +129,20 @@ RSpec.describe Airbrake::Backtrace do
|
|
123
129
|
|
124
130
|
let(:ex) { AirbrakeTestError.new.tap { |e| e.set_backtrace(unknown_bt) } }
|
125
131
|
|
126
|
-
it "
|
127
|
-
expect
|
128
|
-
|
132
|
+
it "returns array of hashes where each unknown frame is marked as 'function'" do
|
133
|
+
expect(
|
134
|
+
described_class.parse(ex, Logger.new('/dev/null'))
|
135
|
+
).to eq([file: nil, line: nil, function: 'a b c 1 23 321 .rb'])
|
136
|
+
end
|
137
|
+
|
138
|
+
it "logs unknown frames as errors" do
|
139
|
+
out = StringIO.new
|
140
|
+
logger = Logger.new(out)
|
141
|
+
|
142
|
+
expect { described_class.parse(ex, logger) }.
|
143
|
+
to change { out.string }.
|
144
|
+
from('').
|
145
|
+
to(/ERROR -- : can't parse 'a b c 1 23 321 .rb'/)
|
129
146
|
end
|
130
147
|
end
|
131
148
|
|
@@ -143,7 +160,34 @@ RSpec.describe Airbrake::Backtrace do
|
|
143
160
|
end
|
144
161
|
|
145
162
|
it "returns a properly formatted array of hashes" do
|
146
|
-
expect(
|
163
|
+
expect(
|
164
|
+
described_class.parse(ex, Logger.new('/dev/null'))
|
165
|
+
).to eq(parsed_backtrace)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context "given an Oracle backtrace" do
|
170
|
+
let(:bt) do
|
171
|
+
['ORA-06512: at "STORE.LI_LICENSES_PACK", line 1945',
|
172
|
+
'ORA-06512: at "ACTIVATION.LI_ACT_LICENSES_PACK", line 101',
|
173
|
+
'ORA-06512: at line 2',
|
174
|
+
'from stmt.c:243:in oci8lib_220.bundle']
|
175
|
+
end
|
176
|
+
|
177
|
+
let(:ex) { OCIError.new.tap { |e| e.set_backtrace(bt) } }
|
178
|
+
|
179
|
+
let(:parsed_backtrace) do
|
180
|
+
[{ file: nil, line: 1945, function: 'STORE.LI_LICENSES_PACK' },
|
181
|
+
{ file: nil, line: 101, function: 'ACTIVATION.LI_ACT_LICENSES_PACK' },
|
182
|
+
{ file: nil, line: 2, function: nil },
|
183
|
+
{ file: 'stmt.c', line: 243, function: 'oci8lib_220.bundle' }]
|
184
|
+
end
|
185
|
+
|
186
|
+
it "returns a properly formatted array of hashes" do
|
187
|
+
stub_const('OCIError', AirbrakeTestError)
|
188
|
+
expect(
|
189
|
+
described_class.parse(ex, Logger.new('/dev/null'))
|
190
|
+
).to eq(parsed_backtrace)
|
147
191
|
end
|
148
192
|
end
|
149
193
|
end
|
@@ -13,7 +13,7 @@ RSpec.describe Airbrake::NestedException do
|
|
13
13
|
Ruby21Error.raise_error('bingo')
|
14
14
|
end
|
15
15
|
rescue Ruby21Error => ex
|
16
|
-
nested_exception = described_class.new(ex)
|
16
|
+
nested_exception = described_class.new(ex, Logger.new('/dev/null'))
|
17
17
|
exceptions = nested_exception.as_json
|
18
18
|
|
19
19
|
expect(exceptions.size).to eq(2)
|
@@ -40,7 +40,7 @@ RSpec.describe Airbrake::NestedException do
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
rescue Ruby21Error => ex
|
43
|
-
nested_exception = described_class.new(ex)
|
43
|
+
nested_exception = described_class.new(ex, Logger.new('/dev/null'))
|
44
44
|
exceptions = nested_exception.as_json
|
45
45
|
|
46
46
|
expect(exceptions.size).to eq(3)
|
@@ -64,7 +64,7 @@ RSpec.describe Airbrake::NestedException do
|
|
64
64
|
end
|
65
65
|
rescue Ruby21Error => ex1
|
66
66
|
ex1.set_backtrace([])
|
67
|
-
nested_exception = described_class.new(ex1)
|
67
|
+
nested_exception = described_class.new(ex1, Logger.new('/dev/null'))
|
68
68
|
exceptions = nested_exception.as_json
|
69
69
|
|
70
70
|
expect(exceptions.size).to eq(2)
|
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.4
|
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-
|
11
|
+
date: 2016-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|