airbrake-ruby 1.4.3 → 1.4.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d0d04742504f2fcec6d259b278ccfde98a0e4700
4
- data.tar.gz: 91e64261180aeebabeee260abf3f3648498f59fa
3
+ metadata.gz: eaad02409926687bb224ce9b635ba755d70ae2ca
4
+ data.tar.gz: 4cf429a9c5cfc4f440ee674ab8c06105447e08a2
5
5
  SHA512:
6
- metadata.gz: 0c0ccf7ede21cefa29a78849b061070a8d569a6c4e866c51e758b9c2dce17dbebf61c80620410c9387e6357d3618a345294aa6447911676a8649cef46b60d45c
7
- data.tar.gz: 9d21bec112c70fd8e38b3c03008488a211a46488c93969fa6ab35534ffadf67c99c298f610eccef61478cbf8eef07e2642d1eba148d4f8e3da3dd3af631aeb8c
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
- (in\s`(?<function>.+)')? # Matches "in `func'" or nothing
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
- stack_frame(match_frame(regexp, stackframe))
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
- match = GENERIC_STACKFRAME_REGEXP.match(stackframe)
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
 
@@ -60,7 +60,7 @@ module Airbrake
60
60
  }.freeze
61
61
 
62
62
  @modifiable_payload = {
63
- errors: NestedException.new(exception).as_json,
63
+ errors: NestedException.new(exception, @config.logger).as_json,
64
64
  context: context(params),
65
65
  environment: {},
66
66
  session: {},
@@ -3,5 +3,5 @@
3
3
  module Airbrake
4
4
  ##
5
5
  # @return [String] the library version
6
- AIRBRAKE_RUBY_VERSION = '1.4.3'.freeze
6
+ AIRBRAKE_RUBY_VERSION = '1.4.4'.freeze
7
7
  end
@@ -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(described_class.parse(AirbrakeTestError.new)).
28
- to eq(parsed_backtrace)
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(described_class.parse(ex)).to eq(parsed_backtrace)
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(described_class.parse(JavaAirbrakeTestError.new)).
73
- to eq(backtrace_array)
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(described_class.parse(ex)).to eq(parsed_backtrace)
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(described_class.parse(ex)).to eq(parsed_backtrace)
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 "raises error" do
127
- expect { described_class.parse(ex) }.
128
- to raise_error(Airbrake::Error, /can't parse/)
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(described_class.parse(ex)).to eq(parsed_backtrace)
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.3
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-06-11 00:00:00.000000000 Z
11
+ date: 2016-07-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec