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 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