airbrake-ruby 4.6.0 → 6.2.2

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.
Files changed (107) hide show
  1. checksums.yaml +5 -5
  2. data/lib/airbrake-ruby/async_sender.rb +24 -109
  3. data/lib/airbrake-ruby/backlog.rb +123 -0
  4. data/lib/airbrake-ruby/backtrace.rb +8 -7
  5. data/lib/airbrake-ruby/benchmark.rb +1 -1
  6. data/lib/airbrake-ruby/code_hunk.rb +1 -1
  7. data/lib/airbrake-ruby/config/processor.rb +77 -0
  8. data/lib/airbrake-ruby/config/validator.rb +9 -3
  9. data/lib/airbrake-ruby/config.rb +78 -19
  10. data/lib/airbrake-ruby/context.rb +51 -0
  11. data/lib/airbrake-ruby/deploy_notifier.rb +1 -1
  12. data/lib/airbrake-ruby/file_cache.rb +6 -0
  13. data/lib/airbrake-ruby/filter_chain.rb +18 -1
  14. data/lib/airbrake-ruby/filters/context_filter.rb +4 -5
  15. data/lib/airbrake-ruby/filters/dependency_filter.rb +1 -0
  16. data/lib/airbrake-ruby/filters/exception_attributes_filter.rb +3 -3
  17. data/lib/airbrake-ruby/filters/gem_root_filter.rb +1 -0
  18. data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +7 -7
  19. data/lib/airbrake-ruby/filters/git_repository_filter.rb +11 -2
  20. data/lib/airbrake-ruby/filters/git_revision_filter.rb +3 -1
  21. data/lib/airbrake-ruby/filters/{keys_whitelist.rb → keys_allowlist.rb} +3 -3
  22. data/lib/airbrake-ruby/filters/{keys_blacklist.rb → keys_blocklist.rb} +3 -3
  23. data/lib/airbrake-ruby/filters/keys_filter.rb +41 -22
  24. data/lib/airbrake-ruby/filters/root_directory_filter.rb +1 -0
  25. data/lib/airbrake-ruby/filters/sql_filter.rb +35 -11
  26. data/lib/airbrake-ruby/filters/system_exit_filter.rb +1 -0
  27. data/lib/airbrake-ruby/filters/thread_filter.rb +6 -5
  28. data/lib/airbrake-ruby/grouppable.rb +12 -0
  29. data/lib/airbrake-ruby/ignorable.rb +1 -2
  30. data/lib/airbrake-ruby/inspectable.rb +2 -2
  31. data/lib/airbrake-ruby/loggable.rb +1 -1
  32. data/lib/airbrake-ruby/mergeable.rb +12 -0
  33. data/lib/airbrake-ruby/monotonic_time.rb +6 -1
  34. data/lib/airbrake-ruby/nested_exception.rb +22 -1
  35. data/lib/airbrake-ruby/notice.rb +12 -17
  36. data/lib/airbrake-ruby/notice_notifier.rb +15 -7
  37. data/lib/airbrake-ruby/performance_breakdown.rb +16 -9
  38. data/lib/airbrake-ruby/performance_notifier.rb +106 -54
  39. data/lib/airbrake-ruby/promise.rb +1 -0
  40. data/lib/airbrake-ruby/query.rb +20 -14
  41. data/lib/airbrake-ruby/queue.rb +65 -0
  42. data/lib/airbrake-ruby/remote_settings/callback.rb +44 -0
  43. data/lib/airbrake-ruby/remote_settings/settings_data.rb +116 -0
  44. data/lib/airbrake-ruby/remote_settings.rb +128 -0
  45. data/lib/airbrake-ruby/request.rb +14 -11
  46. data/lib/airbrake-ruby/response.rb +56 -5
  47. data/lib/airbrake-ruby/stat.rb +27 -34
  48. data/lib/airbrake-ruby/sync_sender.rb +43 -11
  49. data/lib/airbrake-ruby/tdigest.rb +52 -66
  50. data/lib/airbrake-ruby/thread_pool.rb +139 -0
  51. data/lib/airbrake-ruby/time_truncate.rb +2 -2
  52. data/lib/airbrake-ruby/timed_trace.rb +1 -3
  53. data/lib/airbrake-ruby/truncator.rb +10 -4
  54. data/lib/airbrake-ruby/version.rb +11 -1
  55. data/lib/airbrake-ruby.rb +157 -78
  56. metadata +122 -116
  57. data/spec/airbrake_spec.rb +0 -324
  58. data/spec/async_sender_spec.rb +0 -155
  59. data/spec/backtrace_spec.rb +0 -427
  60. data/spec/benchmark_spec.rb +0 -33
  61. data/spec/code_hunk_spec.rb +0 -115
  62. data/spec/config/validator_spec.rb +0 -184
  63. data/spec/config_spec.rb +0 -154
  64. data/spec/deploy_notifier_spec.rb +0 -48
  65. data/spec/file_cache.rb +0 -36
  66. data/spec/filter_chain_spec.rb +0 -92
  67. data/spec/filters/context_filter_spec.rb +0 -23
  68. data/spec/filters/dependency_filter_spec.rb +0 -12
  69. data/spec/filters/exception_attributes_filter_spec.rb +0 -50
  70. data/spec/filters/gem_root_filter_spec.rb +0 -41
  71. data/spec/filters/git_last_checkout_filter_spec.rb +0 -46
  72. data/spec/filters/git_repository_filter.rb +0 -61
  73. data/spec/filters/git_revision_filter_spec.rb +0 -126
  74. data/spec/filters/keys_blacklist_spec.rb +0 -225
  75. data/spec/filters/keys_whitelist_spec.rb +0 -194
  76. data/spec/filters/root_directory_filter_spec.rb +0 -39
  77. data/spec/filters/sql_filter_spec.rb +0 -219
  78. data/spec/filters/system_exit_filter_spec.rb +0 -14
  79. data/spec/filters/thread_filter_spec.rb +0 -277
  80. data/spec/fixtures/notroot.txt +0 -7
  81. data/spec/fixtures/project_root/code.rb +0 -221
  82. data/spec/fixtures/project_root/empty_file.rb +0 -0
  83. data/spec/fixtures/project_root/long_line.txt +0 -1
  84. data/spec/fixtures/project_root/short_file.rb +0 -3
  85. data/spec/fixtures/project_root/vendor/bundle/ignored_file.rb +0 -5
  86. data/spec/helpers.rb +0 -9
  87. data/spec/ignorable_spec.rb +0 -14
  88. data/spec/inspectable_spec.rb +0 -45
  89. data/spec/monotonic_time_spec.rb +0 -12
  90. data/spec/nested_exception_spec.rb +0 -73
  91. data/spec/notice_notifier_spec/options_spec.rb +0 -259
  92. data/spec/notice_notifier_spec.rb +0 -356
  93. data/spec/notice_spec.rb +0 -296
  94. data/spec/performance_breakdown_spec.rb +0 -12
  95. data/spec/performance_notifier_spec.rb +0 -435
  96. data/spec/promise_spec.rb +0 -197
  97. data/spec/query_spec.rb +0 -11
  98. data/spec/request_spec.rb +0 -11
  99. data/spec/response_spec.rb +0 -88
  100. data/spec/spec_helper.rb +0 -100
  101. data/spec/stashable_spec.rb +0 -23
  102. data/spec/stat_spec.rb +0 -47
  103. data/spec/sync_sender_spec.rb +0 -133
  104. data/spec/tdigest_spec.rb +0 -230
  105. data/spec/time_truncate_spec.rb +0 -13
  106. data/spec/timed_trace_spec.rb +0 -125
  107. data/spec/truncator_spec.rb +0 -238
@@ -1,277 +0,0 @@
1
- RSpec.describe Airbrake::Filters::ThreadFilter do
2
- let(:notice) { Airbrake::Notice.new(AirbrakeTestError.new) }
3
-
4
- def new_thread
5
- Thread.new do
6
- th = Thread.current
7
-
8
- # Ensure a thread always has some variable to make sure the
9
- # :fiber_variables Hash is always present.
10
- th[:random_var] = 42
11
- yield(th)
12
- end.join
13
- end
14
-
15
- describe "thread variables" do
16
- shared_examples "expected thread variable" do |var|
17
- it "attaches the thread variable" do
18
- new_thread do |th|
19
- th.thread_variable_set(:bingo, var)
20
- subject.call(notice)
21
- end
22
-
23
- expect(notice[:params][:thread][:thread_variables][:bingo]).to eq(var)
24
- end
25
- end
26
-
27
- context "given nil" do
28
- include_examples "expected thread variable", nil
29
- end
30
-
31
- context "given true" do
32
- include_examples "expected thread variable", true
33
- end
34
-
35
- context "given false" do
36
- include_examples "expected thread variable", false
37
- end
38
-
39
- context "given a String" do
40
- include_examples "expected thread variable", 'bango'
41
- end
42
-
43
- context "given a Symbol" do
44
- include_examples "expected thread variable", :bango
45
- end
46
-
47
- context "given a Regexp" do
48
- include_examples "expected thread variable", /bango/
49
- end
50
-
51
- context "given an Integer" do
52
- include_examples "expected thread variable", 1
53
- end
54
-
55
- context "given a Float" do
56
- include_examples "expected thread variable", 1.01
57
- end
58
-
59
- context "given an Object" do
60
- it "converts it to a String and attaches" do
61
- new_thread do |th|
62
- th.thread_variable_set(:bingo, Object.new)
63
- subject.call(notice)
64
- end
65
-
66
- vars = notice[:params][:thread][:thread_variables]
67
- expect(vars[:bingo]).to match(/\A#<Object:.+>\z/)
68
- end
69
- end
70
-
71
- context "given an Array of nested Hashes with complex objects" do
72
- let(:var) do
73
- [
74
- {
75
- bango: {
76
- bongo: [
77
- {
78
- bish: {
79
- bash: 'foo',
80
- bosh: Object.new
81
- }
82
- }
83
- ]
84
- }
85
- },
86
- 123
87
- ]
88
- end
89
-
90
- it "converts objects to a safe objects" do
91
- new_thread do |th|
92
- th.thread_variable_set(:bingo, var)
93
- subject.call(notice)
94
- end
95
-
96
- vars = notice[:params][:thread][:thread_variables]
97
- expect(vars[:bingo]).to(
98
- match(
99
- [
100
- {
101
- bango: {
102
- bongo: [
103
- {
104
- bish: {
105
- bash: 'foo',
106
- bosh: /\A#<Object:.+>\z/
107
- }
108
- }
109
- ]
110
- }
111
- },
112
- 123
113
- ]
114
- )
115
- )
116
- end
117
- end
118
-
119
- it "ignores thread variables starting with an underscore" do
120
- var = :__recursive_key__
121
-
122
- new_thread do |th|
123
- th.thread_variable_set(var, :bingo)
124
- subject.call(notice)
125
- end
126
-
127
- thread_variables = notice[:params][:thread][:thread_variables]
128
- expect(thread_variables).to be_nil
129
- end
130
- end
131
-
132
- describe "fiber variables" do
133
- shared_examples "expected fiber variable" do |var|
134
- it "attaches the fiber variable" do
135
- new_thread do |th|
136
- th[:bingo] = var
137
- subject.call(notice)
138
- end
139
-
140
- expect(notice[:params][:thread][:fiber_variables][:bingo]).to eq(var)
141
- end
142
- end
143
-
144
- context "given nil" do
145
- include_examples "expected fiber variable", nil
146
- end
147
-
148
- context "given true" do
149
- include_examples "expected fiber variable", true
150
- end
151
-
152
- context "given false" do
153
- include_examples "expected fiber variable", false
154
- end
155
-
156
- context "given a String" do
157
- include_examples "expected fiber variable", 'bango'
158
- end
159
-
160
- context "given a Symbol" do
161
- include_examples "expected fiber variable", :bango
162
- end
163
-
164
- context "given a Regexp" do
165
- include_examples "expected fiber variable", /bango/
166
- end
167
-
168
- context "given an Integer" do
169
- include_examples "expected fiber variable", 1
170
- end
171
-
172
- context "given a Float" do
173
- include_examples "expected fiber variable", 1.01
174
- end
175
-
176
- context "given an Object" do
177
- it "converts it to a String and attaches" do
178
- new_thread do |th|
179
- th[:bingo] = Object.new
180
- subject.call(notice)
181
- end
182
-
183
- vars = notice[:params][:thread][:fiber_variables]
184
- expect(vars[:bingo]).to match(/\A#<Object:.+>\z/)
185
- end
186
- end
187
-
188
- context "given an Array of nested Hashes with complex objects" do
189
- let(:var) do
190
- [
191
- {
192
- bango: {
193
- bongo: [
194
- {
195
- bish: {
196
- bash: 'foo',
197
- bosh: Object.new
198
- }
199
- }
200
- ]
201
- }
202
- },
203
- 123
204
- ]
205
- end
206
-
207
- it "converts objects to a safe objects" do
208
- new_thread do |th|
209
- th[:bingo] = var
210
- subject.call(notice)
211
- end
212
-
213
- vars = notice[:params][:thread][:fiber_variables]
214
- expect(vars[:bingo]).to(
215
- match(
216
- [
217
- {
218
- bango: {
219
- bongo: [
220
- {
221
- bish: {
222
- bash: 'foo',
223
- bosh: /\A#<Object:.+>\z/
224
- }
225
- }
226
- ]
227
- }
228
- },
229
- 123
230
- ]
231
- )
232
- )
233
- end
234
- end
235
- end
236
-
237
- it "appends name", skip: !Thread.current.respond_to?(:name) do
238
- new_thread do |th|
239
- th.name = 'bingo'
240
- subject.call(notice)
241
- end
242
-
243
- expect(notice[:params][:thread][:name]).to eq('bingo')
244
- end
245
-
246
- it "appends thread inspect (self)" do
247
- subject.call(notice)
248
- expect(notice[:params][:thread][:self]).to match(/\A#<Thread:.+ run>\z/)
249
- end
250
-
251
- it "appends thread group" do
252
- subject.call(notice)
253
- expect(notice[:params][:thread][:group][0]).to match(/\A#<Thread:.+ run>\z/)
254
- end
255
-
256
- it "appends priority" do
257
- subject.call(notice)
258
- expect(notice[:params][:thread][:priority]).to eq(0)
259
- end
260
-
261
- it "appends safe_level", skip: Airbrake::JRUBY do
262
- subject.call(notice)
263
- expect(notice[:params][:thread][:safe_level]).to eq(0)
264
- end
265
-
266
- it "ignores fiber variables starting with an underscore" do
267
- key = :__recursive_key__
268
-
269
- new_thread do |th|
270
- th[key] = :bingo
271
- subject.call(notice)
272
- end
273
-
274
- fiber_variables = notice[:params][:thread][:fiber_variables]
275
- expect(fiber_variables[key]).to be_nil
276
- end
277
- end
@@ -1,7 +0,0 @@
1
- This
2
- file
3
- is
4
- not
5
- inside
6
- root
7
- directory
@@ -1,221 +0,0 @@
1
- module Airbrake
2
- ##
3
- # Represents a chunk of information that is meant to be either sent to
4
- # Airbrake or ignored completely.
5
- #
6
- # @since v1.0.0
7
- class Notice
8
- ##
9
- # @return [Hash{Symbol=>String}] the information about the notifier library
10
- NOTIFIER = {
11
- name: 'airbrake-ruby'.freeze,
12
- version: Airbrake::AIRBRAKE_RUBY_VERSION,
13
- url: 'https://github.com/airbrake/airbrake-ruby'.freeze
14
- }.freeze
15
-
16
- ##
17
- # @return [Hash{Symbol=>String,Hash}] the information to be displayed in the
18
- # Context tab in the dashboard
19
- CONTEXT = {
20
- os: RUBY_PLATFORM,
21
- language: "#{RUBY_ENGINE}/#{RUBY_VERSION}".freeze,
22
- notifier: NOTIFIER
23
- }.freeze
24
-
25
- ##
26
- # @return [Integer] the maxium size of the JSON payload in bytes
27
- MAX_NOTICE_SIZE = 64000
28
-
29
- ##
30
- # @return [Integer] the maximum size of hashes, arrays and strings in the
31
- # notice.
32
- PAYLOAD_MAX_SIZE = 10000
33
-
34
- ##
35
- # @return [Array<StandardError>] the list of possible exceptions that might
36
- # be raised when an object is converted to JSON
37
- JSON_EXCEPTIONS = [
38
- IOError,
39
- NotImplementedError,
40
- JSON::GeneratorError,
41
- Encoding::UndefinedConversionError
42
- ].freeze
43
-
44
- # @return [Array<Symbol>] the list of keys that can be be overwritten with
45
- # {Airbrake::Notice#[]=}
46
- WRITABLE_KEYS = %i[notifier context environment session params].freeze
47
-
48
- ##
49
- # @return [Array<Symbol>] parts of a Notice's payload that can be modified
50
- # by the truncator
51
- TRUNCATABLE_KEYS = %i[errors environment session params].freeze
52
-
53
- ##
54
- # @return [String] the name of the host machine
55
- HOSTNAME = Socket.gethostname.freeze
56
-
57
- ##
58
- # @return [String]
59
- DEFAULT_SEVERITY = 'error'.freeze
60
-
61
- ##
62
- # @since v1.7.0
63
- # @return [Hash{Symbol=>Object}] the hash with arbitrary objects to be used
64
- # in filters
65
- attr_reader :stash
66
-
67
- def initialize(config, exception, params = {})
68
- @config = config
69
-
70
- @payload = {
71
- errors: NestedException.new(config, exception).as_json,
72
- context: context,
73
- environment: {
74
- program_name: $PROGRAM_NAME
75
- },
76
- session: {},
77
- params: params
78
- }
79
- @stash = { exception: exception }
80
- @truncator = Airbrake::Truncator.new(PAYLOAD_MAX_SIZE)
81
-
82
- extract_custom_attributes(exception)
83
- end
84
-
85
- ##
86
- # Converts the notice to JSON. Calls +to_json+ on each object inside
87
- # notice's payload. Truncates notices, JSON representation of which is
88
- # bigger than {MAX_NOTICE_SIZE}.
89
- #
90
- # @return [Hash{String=>String}, nil]
91
- def to_json
92
- loop do
93
- begin
94
- json = @payload.to_json
95
- rescue *JSON_EXCEPTIONS => ex
96
- @config.logger.debug("#{LOG_LABEL} `notice.to_json` failed: #{ex.class}: #{ex}")
97
- else
98
- return json if json && json.bytesize <= MAX_NOTICE_SIZE
99
- end
100
-
101
- break if truncate == 0
102
- end
103
- end
104
-
105
- ##
106
- # Ignores a notice. Ignored notices never reach the Airbrake dashboard.
107
- #
108
- # @return [void]
109
- # @see #ignored?
110
- # @note Ignored noticed can't be unignored
111
- def ignore!
112
- @payload = nil
113
- end
114
-
115
- ##
116
- # Checks whether the notice was ignored.
117
- #
118
- # @return [Boolean]
119
- # @see #ignore!
120
- def ignored?
121
- @payload.nil?
122
- end
123
-
124
- ##
125
- # Reads a value from notice's payload.
126
- # @return [Object]
127
- #
128
- # @raise [Airbrake::Error] if the notice is ignored
129
- def [](key)
130
- raise_if_ignored
131
- @payload[key]
132
- end
133
-
134
- ##
135
- # Writes a value to the payload hash. Restricts unrecognized
136
- # writes.
137
- # @example
138
- # notice[:params][:my_param] = 'foobar'
139
- #
140
- # @return [void]
141
- # @raise [Airbrake::Error] if the notice is ignored
142
- # @raise [Airbrake::Error] if the +key+ is not recognized
143
- # @raise [Airbrake::Error] if the root value is not a Hash
144
- def []=(key, value)
145
- raise_if_ignored
146
-
147
- unless WRITABLE_KEYS.include?(key)
148
- raise Airbrake::Error,
149
- ":#{key} is not recognized among #{WRITABLE_KEYS}"
150
- end
151
-
152
- unless value.respond_to?(:to_hash)
153
- raise Airbrake::Error, "Got #{value.class} value, wanted a Hash"
154
- end
155
-
156
- @payload[key] = value.to_hash
157
- end
158
-
159
- private
160
-
161
- def context
162
- {
163
- version: @config.app_version,
164
- # We ensure that root_directory is always a String, so it can always be
165
- # converted to JSON in a predictable manner (when it's a Pathname and in
166
- # Rails environment, it converts to unexpected JSON).
167
- rootDirectory: @config.root_directory.to_s,
168
- environment: @config.environment,
169
-
170
- # Make sure we always send hostname.
171
- hostname: HOSTNAME,
172
-
173
- severity: DEFAULT_SEVERITY
174
- }.merge(CONTEXT).delete_if { |_key, val| val.nil? || val.empty? }
175
- end
176
-
177
- def raise_if_ignored
178
- return unless ignored?
179
- raise Airbrake::Error, 'cannot access ignored notice'
180
- end
181
-
182
- def truncate
183
- TRUNCATABLE_KEYS.each { |key| @truncator.truncate(self[key]) }
184
-
185
- new_max_size = @truncator.reduce_max_size
186
- if new_max_size == 0
187
- @config.logger.error(
188
- "#{LOG_LABEL} truncation failed. File an issue at " \
189
- "https://github.com/airbrake/airbrake-ruby " \
190
- "and attach the following payload: #{@payload}"
191
- )
192
- end
193
-
194
- new_max_size
195
- end
196
-
197
- def extract_custom_attributes(exception)
198
- return unless exception.respond_to?(:to_airbrake)
199
- attributes = nil
200
-
201
- begin
202
- attributes = exception.to_airbrake
203
- rescue StandardError => ex
204
- @config.logger.error(
205
- "#{LOG_LABEL} #{exception.class}#to_airbrake failed: #{ex.class}: #{ex}"
206
- )
207
- end
208
-
209
- return unless attributes
210
-
211
- begin
212
- @payload.merge!(attributes)
213
- rescue TypeError
214
- @config.logger.error(
215
- "#{LOG_LABEL} #{exception.class}#to_airbrake failed:" \
216
- " #{attributes} must be a Hash"
217
- )
218
- end
219
- end
220
- end
221
- end
File without changes
@@ -1 +0,0 @@
1
- loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong line
@@ -1,3 +0,0 @@
1
- module Banana
2
- attr_reader :bingo
3
- end
@@ -1,5 +0,0 @@
1
- module IgnoredFile
2
- def ignore_me
3
- puts 'Anybody here?'
4
- end
5
- end
data/spec/helpers.rb DELETED
@@ -1,9 +0,0 @@
1
- module Helpers
2
- def fixture_path(filename)
3
- File.expand_path(File.join('spec', 'fixtures', filename))
4
- end
5
-
6
- def project_root_path(filename)
7
- fixture_path(File.join('project_root', filename))
8
- end
9
- end
@@ -1,14 +0,0 @@
1
- RSpec.describe Airbrake::Ignorable do
2
- let(:klass) do
3
- mod = subject
4
- Class.new { include(mod) }
5
- end
6
-
7
- it "ignores includee" do
8
- instance = klass.new
9
- expect(instance).not_to be_ignored
10
-
11
- instance.ignore!
12
- expect(instance).to be_ignored
13
- end
14
- end
@@ -1,45 +0,0 @@
1
- RSpec.describe Airbrake::Inspectable do
2
- let(:klass) do
3
- mod = subject
4
- Class.new do
5
- include(mod)
6
-
7
- def initialize
8
- @config = Airbrake::Config.new
9
- @filter_chain = nil
10
- end
11
- end
12
- end
13
-
14
- describe "#inspect" do
15
- it "displays object information" do
16
- instance = klass.new
17
- expect(instance.inspect).to match(/
18
- #<:0x\w+\s
19
- project_id=""\s
20
- project_key=""\s
21
- host="http.+"\s
22
- filter_chain=nil>
23
- /x)
24
- end
25
- end
26
-
27
- describe "#pretty_print" do
28
- it "displays object information in a beautiful way" do
29
- q = PP.new
30
-
31
- instance = klass.new
32
- # Guarding is needed to fix JRuby failure:
33
- # NoMethodError: undefined method `[]' for nil:NilClass
34
- q.guard_inspect_key { instance.pretty_print(q) }
35
-
36
- expect(q.output).to match(/
37
- #<:0x\w+\s
38
- project_id=""\s
39
- project_key=""\s
40
- host="http.+"\s
41
- filter_chain=nil
42
- /x)
43
- end
44
- end
45
- end
@@ -1,12 +0,0 @@
1
- RSpec.describe Airbrake::MonotonicTime do
2
- describe ".time_in_ms" do
3
- it "returns monotonic time in milliseconds" do
4
- expect(subject.time_in_ms).to be_a(Float)
5
- end
6
-
7
- it "always returns time in the future" do
8
- old_time = subject.time_in_ms
9
- expect(subject.time_in_ms).to be > old_time
10
- end
11
- end
12
- end
@@ -1,73 +0,0 @@
1
- RSpec.describe Airbrake::NestedException do
2
- describe "#as_json" do
3
- context "given exceptions with backtraces" do
4
- it "unwinds nested exceptions" do
5
- begin
6
- begin
7
- raise AirbrakeTestError
8
- rescue AirbrakeTestError
9
- Ruby21Error.raise_error('bingo')
10
- end
11
- rescue Ruby21Error => ex
12
- nested_exception = described_class.new(ex)
13
- exceptions = nested_exception.as_json
14
-
15
- expect(exceptions.size).to eq(2)
16
- expect(exceptions[0][:message]).to eq('bingo')
17
- expect(exceptions[1][:message]).to eq('App crashed!')
18
- expect(exceptions[0][:backtrace]).not_to be_empty
19
- expect(exceptions[1][:backtrace]).not_to be_empty
20
- end
21
- end
22
-
23
- it "unwinds no more than 3 nested exceptions" do
24
- begin
25
- begin
26
- raise AirbrakeTestError
27
- rescue AirbrakeTestError
28
- begin
29
- Ruby21Error.raise_error('bongo')
30
- rescue Ruby21Error
31
- begin
32
- Ruby21Error.raise_error('bango')
33
- rescue Ruby21Error
34
- Ruby21Error.raise_error('bingo')
35
- end
36
- end
37
- end
38
- rescue Ruby21Error => ex
39
- nested_exception = described_class.new(ex)
40
- exceptions = nested_exception.as_json
41
-
42
- expect(exceptions.size).to eq(3)
43
- expect(exceptions[0][:message]).to eq('bingo')
44
- expect(exceptions[1][:message]).to eq('bango')
45
- expect(exceptions[2][:message]).to eq('bongo')
46
- expect(exceptions[0][:backtrace]).not_to be_empty
47
- expect(exceptions[1][:backtrace]).not_to be_empty
48
- end
49
- end
50
- end
51
-
52
- context "given exceptions without backtraces" do
53
- it "sets backtrace to nil" do
54
- begin
55
- begin
56
- raise AirbrakeTestError
57
- rescue AirbrakeTestError => ex2
58
- ex2.set_backtrace([])
59
- Ruby21Error.raise_error('bingo')
60
- end
61
- rescue Ruby21Error => ex1
62
- ex1.set_backtrace([])
63
- nested_exception = described_class.new(ex1)
64
- exceptions = nested_exception.as_json
65
-
66
- expect(exceptions.size).to eq(2)
67
- expect(exceptions[0][:backtrace]).to be_empty
68
- expect(exceptions[1][:backtrace]).to be_empty
69
- end
70
- end
71
- end
72
- end
73
- end