airbrake-ruby 4.10.1 → 4.12.0

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
  SHA256:
3
- metadata.gz: 48ada7ef05512e70461f565b7d0f501d3109c1b6934449106cb5006bdb7281db
4
- data.tar.gz: 343e472ce390b3882543423bdb8ee50a4cc311ff3907f557a553fa57631305d7
3
+ metadata.gz: 8c5e41d6b33c6a201ef67d32e32e69bbef6e560c1af80dc19ae8f4192d6b84fd
4
+ data.tar.gz: 34e30b5ce530edc18c512ba0be5392a2c53cdee68ec23eb43174e9690715f821
5
5
  SHA512:
6
- metadata.gz: 7d68da52b648cff0b0e4c64016f5e0dd6d0143f1cf547e5604ed41ee58f9f03511e689c3acd35eef7df632d998cb56a416212ff1c952c9331ec173459641c20c
7
- data.tar.gz: '079ac6ce90ab7b885561e7f17ab6d770630d59cbaa066664c2b0c2cabd4c28b2c594101863ef04b8e4a92e369ac5e9f3c886159f227eec370a485544cf035250'
6
+ metadata.gz: '0081a23db3f3ff08f56382e97a67685a7c28eb81c5c93963a440a5f216ddf322ffaf8dae6be14a1394edc079dbd1644511f817693a14eebb3e097243f03f74c9'
7
+ data.tar.gz: c9c58c197046e16f7706cddbfb4caab70837f03b457418ff22f756499efe6bd98762eca8547a9e716af9d04e20c53a4440a9ca83affc7c1713623d3a191cb560
@@ -328,9 +328,8 @@ module Airbrake
328
328
  notice_notifier.merge_context(context)
329
329
  end
330
330
 
331
- # Increments request statistics of a certain +route+ that was invoked on
332
- # +start_time+ and ended on +end_time+ with +method+, and returned
333
- # +status_code+.
331
+ # Increments request statistics of a certain +route+ invoked with +method+,
332
+ # which returned +status_code+.
334
333
  #
335
334
  # After a certain amount of time (n seconds) the aggregated route
336
335
  # information will be sent to Airbrake.
@@ -343,8 +342,7 @@ module Airbrake
343
342
  # func: 'do_stuff',
344
343
  # file: 'app/models/foo.rb',
345
344
  # line: 452,
346
- # start_time: timestamp,
347
- # end_time: Time.now
345
+ # timing: 123.45 # ms
348
346
  # )
349
347
  #
350
348
  # @param [Hash{Symbol=>Object}] request_info
@@ -358,8 +356,8 @@ module Airbrake
358
356
  # called the query (optional)
359
357
  # @option request_info [Integer] :line The line that executes the query
360
358
  # (optional)
361
- # @option request_info [Date] :start_time When the request started
362
- # @option request_info [Time] :end_time When the request ended (optional)
359
+ # @option request_info [Float] :timing How much time it took to process the
360
+ # request (in ms)
363
361
  # @param [Hash] stash What needs to be appeneded to the stash, so it's
364
362
  # available in filters
365
363
  # @return [void]
@@ -371,9 +369,8 @@ module Airbrake
371
369
  performance_notifier.notify(request)
372
370
  end
373
371
 
374
- # Synchronously Increments request statistics of a certain +route+ that was
375
- # invoked on +start_time+ and ended on +end_time+ with +method+, and
376
- # returned +status_code+.
372
+ # Synchronously increments request statistics of a certain +route+ invoked
373
+ # with +method+, which returned +status_code+.
377
374
  # @since v4.10.0
378
375
  # @see .notify_request
379
376
  def notify_request_sync(request_info, stash = {})
@@ -382,9 +379,8 @@ module Airbrake
382
379
  performance_notifier.notify_sync(request)
383
380
  end
384
381
 
385
- # Increments SQL statistics of a certain +query+ that was invoked on
386
- # +start_time+ and finished on +end_time+. When +method+ and +route+ are
387
- # provided, the query is grouped by these parameters.
382
+ # Increments SQL statistics of a certain +query+. When +method+ and +route+
383
+ # are provided, the query is grouped by these parameters.
388
384
  #
389
385
  # After a certain amount of time (n seconds) the aggregated query
390
386
  # information will be sent to Airbrake.
@@ -394,18 +390,17 @@ module Airbrake
394
390
  # method: 'GET',
395
391
  # route: '/things',
396
392
  # query: 'SELECT * FROM things',
397
- # start_time: timestamp,
398
- # end_time: Time.now
393
+ # timing: 123.45 # ms
399
394
  # )
400
395
  #
401
396
  # @param [Hash{Symbol=>Object}] query_info
402
- # @option request_info [String] :method The HTTP method that triggered this
397
+ # @option query_info [String] :method The HTTP method that triggered this
403
398
  # SQL query (optional)
404
- # @option request_info [String] :route The route that triggered this SQL
399
+ # @option query_info [String] :route The route that triggered this SQL
405
400
  # query (optional)
406
- # @option request_info [String] :query The query that was executed
407
- # @option request_info [Date] :start_time When the query started executing
408
- # @option request_info [Time] :end_time When the query finished (optional)
401
+ # @option query_info [String] :query The query that was executed
402
+ # @option query_info [Float] :timing How much time it took to process the
403
+ # query (in ms)
409
404
  # @param [Hash] stash What needs to be appeneded to the stash, so it's
410
405
  # available in filters
411
406
  # @return [void]
@@ -417,9 +412,9 @@ module Airbrake
417
412
  performance_notifier.notify(query)
418
413
  end
419
414
 
420
- # Synchronously increments SQL statistics of a certain +query+ that was
421
- # invoked on +start_time+ and finished on +end_time+. When +method+ and
422
- # +route+ are provided, the query is grouped by these parameters.
415
+ # Synchronously increments SQL statistics of a certain +query+. When
416
+ # +method+ and +route+ are provided, the query is grouped by these
417
+ # parameters.
423
418
  # @since v4.10.0
424
419
  # @see .notify_query
425
420
  def notify_query_sync(query_info, stash = {})
@@ -436,8 +431,7 @@ module Airbrake
436
431
  # route: '/thing/:id/create',
437
432
  # response_type: 'json',
438
433
  # groups: { db: 24.0, view: 0.4 }, # ms
439
- # start_time: timestamp,
440
- # end_time: Time.now
434
+ # timing: 123.45 # ms
441
435
  # )
442
436
  #
443
437
  # @param [Hash{Symbol=>Object}] breakdown_info
@@ -445,7 +439,8 @@ module Airbrake
445
439
  # @option breakdown_info [String] :route
446
440
  # @option breakdown_info [String] :response_type
447
441
  # @option breakdown_info [Array<Hash{Symbol=>Float}>] :groups
448
- # @option breakdown_info [Date] :start_time
442
+ # @option breakdown_info [Float] :timing How much time it took to process
443
+ # the performance breakdown (in ms)
449
444
  # @param [Hash] stash What needs to be appeneded to the stash, so it's
450
445
  # available in filters
451
446
  # @return [void]
@@ -481,6 +476,8 @@ module Airbrake
481
476
  # failed
482
477
  # @option queue_info [Array<Hash{Symbol=>Float}>] :groups Where the job
483
478
  # spent its time
479
+ # @option breakdown_info [Float] :timing How much time it took to process
480
+ # the queue (in ms)
484
481
  # @param [Hash] stash What needs to be appended to the stash, so it's
485
482
  # available in filters
486
483
  # @return [void]
@@ -2,7 +2,7 @@ module Airbrake
2
2
  # Benchmark benchmarks Ruby code.
3
3
  #
4
4
  # @since v4.2.4
5
- # @api private
5
+ # @api public
6
6
  class Benchmark
7
7
  # Measures monotonic time for the given operation.
8
8
  #
@@ -101,6 +101,12 @@ module Airbrake
101
101
  # @since v4.6.0
102
102
  attr_accessor :query_stats
103
103
 
104
+ # @return [Boolean] true if the library should send job/queue/worker stats
105
+ # to Airbrake, false otherwise
106
+ # @api public
107
+ # @since v4.12.0
108
+ attr_accessor :job_stats
109
+
104
110
  class << self
105
111
  # @return [Config]
106
112
  attr_writer :instance
@@ -139,6 +145,7 @@ module Airbrake
139
145
  self.performance_stats = true
140
146
  self.performance_stats_flush_period = 15
141
147
  self.query_stats = true
148
+ self.job_stats = true
142
149
 
143
150
  merge(user_config)
144
151
  end
@@ -213,6 +220,8 @@ module Airbrake
213
220
  promise.reject("The Performance Stats feature is disabled")
214
221
  elsif resource.is_a?(Airbrake::Query) && !query_stats
215
222
  promise.reject("The Query Stats feature is disabled")
223
+ elsif resource.is_a?(Airbrake::Queue) && !job_stats
224
+ promise.reject("The Job Stats feature is disabled")
216
225
  else
217
226
  promise
218
227
  end
@@ -55,7 +55,8 @@ module Airbrake
55
55
  def build_notice(exception, params = {})
56
56
  if @async_sender.closed?
57
57
  raise Airbrake::Error,
58
- "attempted to build #{exception} with closed Airbrake instance"
58
+ "Airbrake is closed; can't build exception: " \
59
+ "#{exception.class}: #{exception}"
59
60
  end
60
61
 
61
62
  if exception.is_a?(Airbrake::Notice)
@@ -7,7 +7,8 @@ module Airbrake
7
7
  # @since v4.2.0
8
8
  # rubocop:disable Metrics/BlockLength, Metrics/ParameterLists
9
9
  PerformanceBreakdown = Struct.new(
10
- :method, :route, :response_type, :groups, :start_time, :end_time
10
+ :method, :route, :response_type, :groups, :start_time, :end_time, :timing,
11
+ :time
11
12
  ) do
12
13
  include HashKeyable
13
14
  include Ignorable
@@ -19,11 +20,15 @@ module Airbrake
19
20
  route:,
20
21
  response_type:,
21
22
  groups:,
22
- start_time:,
23
- end_time: start_time + 1
23
+ start_time: Time.now,
24
+ end_time: start_time + 1,
25
+ timing: nil,
26
+ time: Time.now
24
27
  )
25
- @start_time_utc = TimeTruncate.utc_truncate_minutes(start_time)
26
- super(method, route, response_type, groups, start_time, end_time)
28
+ @time_utc = TimeTruncate.utc_truncate_minutes(time)
29
+ super(
30
+ method, route, response_type, groups, start_time, end_time, timing, time
31
+ )
27
32
  end
28
33
 
29
34
  def destination
@@ -39,7 +44,7 @@ module Airbrake
39
44
  'method' => method,
40
45
  'route' => route,
41
46
  'responseType' => response_type,
42
- 'time' => @start_time_utc,
47
+ 'time' => @time_utc,
43
48
  }.delete_if { |_key, val| val.nil? }
44
49
  end
45
50
  end
@@ -62,7 +62,7 @@ module Airbrake
62
62
  @payload[resource] = { total: Airbrake::Stat.new }
63
63
  end
64
64
 
65
- @payload[resource][:total].increment(resource.start_time, resource.end_time)
65
+ update_total(resource, @payload[resource][:total])
66
66
 
67
67
  resource.groups.each do |name, ms|
68
68
  @payload[resource][name] ||= Airbrake::Stat.new
@@ -70,6 +70,19 @@ module Airbrake
70
70
  end
71
71
  end
72
72
 
73
+ def update_total(resource, total)
74
+ if resource.timing
75
+ total.increment_ms(resource.timing)
76
+ else
77
+ loc = caller_locations(6..6).first
78
+ Kernel.warn(
79
+ "#{loc.path}:#{loc.lineno}: warning: :start_time and :end_time are " \
80
+ "deprecated. Use :timing & :time instead",
81
+ )
82
+ total.increment(resource.start_time, resource.end_time)
83
+ end
84
+ end
85
+
73
86
  def schedule_flush
74
87
  return if @payload.empty?
75
88
 
@@ -107,14 +120,13 @@ module Airbrake
107
120
  end
108
121
 
109
122
  def send_resource(resource, sync:)
110
- promise = @config.check_configuration
111
- return promise if promise.rejected?
112
-
113
- promise = @config.check_performance_options(resource)
123
+ promise = check_configuration(resource)
114
124
  return promise if promise.rejected?
115
125
 
116
126
  @filter_chain.refine(resource)
117
- return if resource.ignored?
127
+ if resource.ignored?
128
+ return Promise.new.reject("#{resource.class} was ignored by a filter")
129
+ end
118
130
 
119
131
  @mutex.synchronize do
120
132
  update_payload(resource)
@@ -126,6 +138,20 @@ module Airbrake
126
138
  end
127
139
  end
128
140
 
141
+ def check_configuration(resource)
142
+ promise = @config.check_configuration
143
+ return promise if promise.rejected?
144
+
145
+ promise = @config.check_performance_options(resource)
146
+ return promise if promise.rejected?
147
+
148
+ if resource.timing && resource.timing == 0
149
+ return Promise.new.reject(':timing cannot be zero')
150
+ end
151
+
152
+ Promise.new
153
+ end
154
+
129
155
  def send(sender, payload, promise)
130
156
  signature = "#{self.class.name}##{__method__}"
131
157
  raise "#{signature}: payload (#{payload}) cannot be empty. Race?" if payload.none?
@@ -6,7 +6,8 @@ module Airbrake
6
6
  # @since v3.2.0
7
7
  # rubocop:disable Metrics/ParameterLists, Metrics/BlockLength
8
8
  Query = Struct.new(
9
- :method, :route, :query, :func, :file, :line, :start_time, :end_time
9
+ :method, :route, :query, :func, :file, :line, :start_time, :end_time,
10
+ :timing, :time
10
11
  ) do
11
12
  include HashKeyable
12
13
  include Ignorable
@@ -21,11 +22,16 @@ module Airbrake
21
22
  func: nil,
22
23
  file: nil,
23
24
  line: nil,
24
- start_time:,
25
- end_time: start_time + 1
25
+ start_time: Time.now,
26
+ end_time: start_time + 1,
27
+ timing: nil,
28
+ time: Time.now
26
29
  )
27
- @start_time_utc = TimeTruncate.utc_truncate_minutes(start_time)
28
- super(method, route, query, func, file, line, start_time, end_time)
30
+ @time_utc = TimeTruncate.utc_truncate_minutes(time)
31
+ super(
32
+ method, route, query, func, file, line, start_time, end_time, timing,
33
+ time
34
+ )
29
35
  end
30
36
 
31
37
  def destination
@@ -41,7 +47,7 @@ module Airbrake
41
47
  'method' => method,
42
48
  'route' => route,
43
49
  'query' => query,
44
- 'time' => @start_time_utc,
50
+ 'time' => @time_utc,
45
51
  'function' => func,
46
52
  'file' => file,
47
53
  'line' => line,
@@ -4,8 +4,10 @@ module Airbrake
4
4
  # @see Airbrake.notify_queue
5
5
  # @api public
6
6
  # @since v4.9.0
7
- # rubocop:disable Metrics/BlockLength
8
- Queue = Struct.new(:queue, :error_count, :groups, :start_time, :end_time) do
7
+ # rubocop:disable Metrics/BlockLength, Metrics/ParameterLists
8
+ Queue = Struct.new(
9
+ :queue, :error_count, :groups, :start_time, :end_time, :timing, :time
10
+ ) do
9
11
  include HashKeyable
10
12
  include Ignorable
11
13
  include Stashable
@@ -15,10 +17,12 @@ module Airbrake
15
17
  error_count:,
16
18
  groups: {},
17
19
  start_time: Time.now,
18
- end_time: start_time + 1
20
+ end_time: start_time + 1,
21
+ timing: nil,
22
+ time: Time.now
19
23
  )
20
- @start_time_utc = TimeTruncate.utc_truncate_minutes(start_time)
21
- super(queue, error_count, groups, start_time, end_time)
24
+ @time_utc = TimeTruncate.utc_truncate_minutes(time)
25
+ super(queue, error_count, groups, start_time, end_time, timing, time)
22
26
  end
23
27
 
24
28
  def destination
@@ -33,14 +37,14 @@ module Airbrake
33
37
  {
34
38
  'queue' => queue,
35
39
  'errorCount' => error_count,
36
- 'time' => @start_time_utc,
40
+ 'time' => @time_utc,
37
41
  }
38
42
  end
39
43
 
40
44
  def hash
41
45
  {
42
46
  'queue' => queue,
43
- 'time' => @start_time_utc,
47
+ 'time' => @time_utc,
44
48
  }.hash
45
49
  end
46
50
 
@@ -48,5 +52,5 @@ module Airbrake
48
52
  self.error_count += other.error_count
49
53
  end
50
54
  end
51
- # rubocop:enable Metrics/BlockLength
55
+ # rubocop:enable Metrics/BlockLength, Metrics/ParameterLists
52
56
  end
@@ -4,8 +4,10 @@ module Airbrake
4
4
  # @see Airbrake.notify_request
5
5
  # @api public
6
6
  # @since v3.2.0
7
- # rubocop:disable Metrics/BlockLength
8
- Request = Struct.new(:method, :route, :status_code, :start_time, :end_time) do
7
+ # rubocop:disable Metrics/BlockLength, Metrics/ParameterLists
8
+ Request = Struct.new(
9
+ :method, :route, :status_code, :start_time, :end_time, :timing, :time
10
+ ) do
9
11
  include HashKeyable
10
12
  include Ignorable
11
13
  include Stashable
@@ -16,11 +18,13 @@ module Airbrake
16
18
  method:,
17
19
  route:,
18
20
  status_code:,
19
- start_time:,
20
- end_time: start_time + 1
21
+ start_time: Time.now,
22
+ end_time: start_time + 1,
23
+ timing: nil,
24
+ time: Time.now
21
25
  )
22
- @start_time_utc = TimeTruncate.utc_truncate_minutes(start_time)
23
- super(method, route, status_code, start_time, end_time)
26
+ @time_utc = TimeTruncate.utc_truncate_minutes(time)
27
+ super(method, route, status_code, start_time, end_time, timing, time)
24
28
  end
25
29
 
26
30
  def destination
@@ -36,9 +40,9 @@ module Airbrake
36
40
  'method' => method,
37
41
  'route' => route,
38
42
  'statusCode' => status_code,
39
- 'time' => @start_time_utc,
43
+ 'time' => @time_utc,
40
44
  }.delete_if { |_key, val| val.nil? }
41
45
  end
42
46
  end
43
- # rubocop:enable Metrics/BlockLength
47
+ # rubocop:enable Metrics/BlockLength, Metrics/ParameterLists
44
48
  end
@@ -2,5 +2,5 @@
2
2
  # More information: http://semver.org/
3
3
  module Airbrake
4
4
  # @return [String] the library version
5
- AIRBRAKE_RUBY_VERSION = '4.10.1'.freeze
5
+ AIRBRAKE_RUBY_VERSION = '4.12.0'.freeze
6
6
  end
@@ -171,7 +171,7 @@ RSpec.describe Airbrake do
171
171
  method: 'GET',
172
172
  route: '/',
173
173
  status_code: 200,
174
- start_time: Time.now,
174
+ timing: 1,
175
175
  )
176
176
  end
177
177
  end
@@ -187,7 +187,7 @@ RSpec.describe Airbrake do
187
187
  method: 'GET',
188
188
  route: '/',
189
189
  status_code: 200,
190
- start_time: Time.now,
190
+ timing: 1,
191
191
  },
192
192
  request_id: 1,
193
193
  )
@@ -204,7 +204,7 @@ RSpec.describe Airbrake do
204
204
  method: 'GET',
205
205
  route: '/',
206
206
  status_code: 200,
207
- start_time: Time.now,
207
+ timing: 1,
208
208
  },
209
209
  request_id: 1,
210
210
  )
@@ -222,7 +222,7 @@ RSpec.describe Airbrake do
222
222
  method: 'GET',
223
223
  route: '/',
224
224
  query: '',
225
- start_time: Time.now,
225
+ timing: 1,
226
226
  )
227
227
  end
228
228
  end
@@ -238,7 +238,7 @@ RSpec.describe Airbrake do
238
238
  method: 'GET',
239
239
  route: '/',
240
240
  query: '',
241
- start_time: Time.now,
241
+ timing: 1,
242
242
  },
243
243
  request_id: 1,
244
244
  )
@@ -255,7 +255,7 @@ RSpec.describe Airbrake do
255
255
  method: 'GET',
256
256
  route: '/',
257
257
  query: '',
258
- start_time: Time.now,
258
+ timing: 1,
259
259
  },
260
260
  request_id: 1,
261
261
  )
@@ -273,7 +273,7 @@ RSpec.describe Airbrake do
273
273
  method: 'GET',
274
274
  route: '/',
275
275
  query: '',
276
- start_time: Time.now,
276
+ timing: 1,
277
277
  )
278
278
  end
279
279
  end
@@ -292,7 +292,7 @@ RSpec.describe Airbrake do
292
292
  route: '/',
293
293
  response_type: :html,
294
294
  groups: {},
295
- start_time: Time.now,
295
+ timing: 1,
296
296
  },
297
297
  request_id: 1,
298
298
  )
@@ -310,7 +310,7 @@ RSpec.describe Airbrake do
310
310
  route: '/',
311
311
  response_type: :html,
312
312
  groups: {},
313
- start_time: Time.now,
313
+ timing: 1,
314
314
  },
315
315
  request_id: 1,
316
316
  )
@@ -22,6 +22,7 @@ RSpec.describe Airbrake::Config do
22
22
  its(:performance_stats) { is_expected.to eq(true) }
23
23
  its(:performance_stats_flush_period) { is_expected.to eq(15) }
24
24
  its(:query_stats) { is_expected.to eq(true) }
25
+ its(:job_stats) { is_expected.to eq(true) }
25
26
 
26
27
  describe "#new" do
27
28
  context "when user config is passed" do
@@ -110,9 +111,7 @@ RSpec.describe Airbrake::Config do
110
111
 
111
112
  describe "#check_performance_options" do
112
113
  it "returns a promise" do
113
- resource = Airbrake::Query.new(
114
- method: '', route: '', query: '', start_time: Time.now,
115
- )
114
+ resource = Airbrake::Query.new(method: '', route: '', query: '', timing: 1)
116
115
  expect(subject.check_performance_options(resource))
117
116
  .to be_an(Airbrake::Promise)
118
117
  end
@@ -122,7 +121,7 @@ RSpec.describe Airbrake::Config do
122
121
 
123
122
  let(:resource) do
124
123
  Airbrake::Request.new(
125
- method: 'GET', route: '/foo', status_code: 200, start_time: Time.new,
124
+ method: 'GET', route: '/foo', status_code: 200, timing: 1,
126
125
  )
127
126
  end
128
127
 
@@ -138,9 +137,7 @@ RSpec.describe Airbrake::Config do
138
137
  before { subject.query_stats = false }
139
138
 
140
139
  let(:resource) do
141
- Airbrake::Query.new(
142
- method: 'GET', route: '/foo', query: '', start_time: Time.new,
143
- )
140
+ Airbrake::Query.new(method: 'GET', route: '/foo', query: '', timing: 1)
144
141
  end
145
142
 
146
143
  it "returns a rejected promise" do
@@ -150,5 +147,20 @@ RSpec.describe Airbrake::Config do
150
147
  )
151
148
  end
152
149
  end
150
+
151
+ context "when job stats are disabled" do
152
+ before { subject.job_stats = false }
153
+
154
+ let(:resource) do
155
+ Airbrake::Queue.new(queue: 'foo_queue', error_count: 0, timing: 1)
156
+ end
157
+
158
+ it "returns a rejected promise" do
159
+ promise = subject.check_performance_options(resource)
160
+ expect(promise.value).to eq(
161
+ 'error' => "The Job Stats feature is disabled",
162
+ )
163
+ end
164
+ end
153
165
  end
154
166
  end
@@ -13,9 +13,7 @@ RSpec.describe Airbrake::Filters::SqlFilter do
13
13
  shared_examples "query blacklisting" do |query, opts|
14
14
  it "ignores '#{query}'" do
15
15
  filter = described_class.new('postgres')
16
- q = Airbrake::Query.new(
17
- query: query, method: 'GET', route: '/', start_time: Time.now,
18
- )
16
+ q = Airbrake::Query.new(query: query, method: 'GET', route: '/', timing: 1)
19
17
  filter.call(q)
20
18
 
21
19
  expect(q.ignored?).to eq(opts[:should_ignore])
@@ -328,9 +328,9 @@ RSpec.describe Airbrake::NoticeNotifier do
328
328
  end
329
329
 
330
330
  it "raises error" do
331
- expect { subject.build_notice(Exception.new) }.to raise_error(
331
+ expect { subject.build_notice(Exception.new('oops')) }.to raise_error(
332
332
  Airbrake::Error,
333
- 'attempted to build Exception with closed Airbrake instance',
333
+ "Airbrake is closed; can't build exception: Exception: oops",
334
334
  )
335
335
  end
336
336
  end
@@ -16,6 +16,7 @@ RSpec.describe Airbrake::PerformanceNotifier do
16
16
  performance_stats: true,
17
17
  performance_stats_flush_period: 0,
18
18
  query_stats: true,
19
+ job_stats: true,
19
20
  )
20
21
  end
21
22
 
@@ -29,8 +30,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
29
30
  func: 'foo',
30
31
  file: 'foo.rb',
31
32
  line: 123,
32
- start_time: Time.new(2018, 1, 1, 0, 49, 0, 0),
33
- end_time: Time.new(2018, 1, 1, 0, 50, 0, 0),
33
+ timing: 60000,
34
+ time: Time.new(2018, 1, 1, 0, 49, 0, 0),
34
35
  ),
35
36
  )
36
37
  subject.close
@@ -59,8 +60,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
59
60
  method: 'POST',
60
61
  route: '/foo',
61
62
  status_code: 200,
62
- start_time: Time.new(2018, 1, 1, 0, 49, 0, 0),
63
- end_time: Time.new(2018, 1, 1, 0, 50, 0, 0),
63
+ timing: 60000,
64
+ time: Time.new(2018, 1, 1, 0, 49, 0, 0),
64
65
  ),
65
66
  )
66
67
  subject.close
@@ -86,8 +87,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
86
87
  method: 'DELETE',
87
88
  route: '/routes-breakdowns',
88
89
  response_type: 'json',
89
- start_time: Time.new(2018, 1, 1, 0, 49, 0, 0),
90
- end_time: Time.new(2018, 1, 1, 0, 50, 0, 0),
90
+ timing: 60000,
91
+ time: Time.new(2018, 1, 1, 0, 49, 0, 0),
91
92
  groups: { db: 131, view: 421 },
92
93
  ),
93
94
  )
@@ -128,8 +129,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
128
129
  queue: 'emails',
129
130
  error_count: 2,
130
131
  groups: { redis: 131, sql: 421 },
131
- start_time: Time.new(2018, 1, 1, 0, 49, 0, 0),
132
- end_time: Time.new(2018, 1, 1, 0, 50, 0, 0),
132
+ timing: 60000,
133
+ time: Time.new(2018, 1, 1, 0, 49, 0, 0),
133
134
  ),
134
135
  )
135
136
  subject.close
@@ -168,7 +169,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
168
169
  method: 'GET',
169
170
  route: '/foo',
170
171
  status_code: 200,
171
- start_time: Time.new(2018, 1, 1, 0, 0, 20, 0),
172
+ timing: 60000,
173
+ time: Time.new(2018, 1, 1, 0, 0, 20, 0),
172
174
  ),
173
175
  )
174
176
  subject.close
@@ -184,7 +186,7 @@ RSpec.describe Airbrake::PerformanceNotifier do
184
186
  method: 'GET',
185
187
  route: '/foo',
186
188
  status_code: 200,
187
- start_time: Time.new(2018, 1, 1, 0, 0, 20, 0),
189
+ timing: 213,
188
190
  ),
189
191
  )
190
192
  subject.notify(
@@ -192,7 +194,7 @@ RSpec.describe Airbrake::PerformanceNotifier do
192
194
  method: 'GET',
193
195
  route: '/foo',
194
196
  status_code: 200,
195
- start_time: Time.new(2018, 1, 1, 0, 0, 50, 0),
197
+ timing: 123,
196
198
  ),
197
199
  )
198
200
  subject.close
@@ -208,8 +210,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
208
210
  method: 'GET',
209
211
  route: '/foo',
210
212
  status_code: 200,
211
- start_time: Time.new(2018, 1, 1, 0, 0, 49, 0),
212
- end_time: Time.new(2018, 1, 1, 0, 0, 50, 0),
213
+ timing: 1000,
214
+ time: Time.new(2018, 1, 1, 0, 0, 49, 0),
213
215
  ),
214
216
  )
215
217
  subject.notify(
@@ -217,8 +219,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
217
219
  method: 'GET',
218
220
  route: '/foo',
219
221
  status_code: 200,
220
- start_time: Time.new(2018, 1, 1, 0, 1, 49, 0),
221
- end_time: Time.new(2018, 1, 1, 0, 1, 55, 0),
222
+ timing: 6000,
223
+ time: Time.new(2018, 1, 1, 0, 1, 49, 0),
222
224
  ),
223
225
  )
224
226
  subject.close
@@ -244,8 +246,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
244
246
  method: 'GET',
245
247
  route: '/foo',
246
248
  status_code: 200,
247
- start_time: Time.new(2018, 1, 1, 0, 49, 0, 0),
248
- end_time: Time.new(2018, 1, 1, 0, 50, 0, 0),
249
+ timing: 60000,
250
+ time: Time.new(2018, 1, 1, 0, 49, 0, 0),
249
251
  ),
250
252
  )
251
253
  subject.notify(
@@ -253,8 +255,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
253
255
  method: 'POST',
254
256
  route: '/foo',
255
257
  status_code: 200,
256
- start_time: Time.new(2018, 1, 1, 0, 49, 0, 0),
257
- end_time: Time.new(2018, 1, 1, 0, 50, 0, 0),
258
+ timing: 60000,
259
+ time: Time.new(2018, 1, 1, 0, 49, 0, 0),
258
260
  ),
259
261
  )
260
262
  subject.close
@@ -280,8 +282,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
280
282
  method: 'DELETE',
281
283
  route: '/routes-breakdowns',
282
284
  response_type: 'json',
283
- start_time: Time.new(2018, 1, 1, 0, 0, 20, 0),
284
- end_time: Time.new(2018, 1, 1, 0, 0, 22, 0),
285
+ timing: 2000,
286
+ time: Time.new(2018, 1, 1, 0, 0, 20, 0),
285
287
  groups: { db: 131, view: 421 },
286
288
  ),
287
289
  )
@@ -290,8 +292,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
290
292
  method: 'DELETE',
291
293
  route: '/routes-breakdowns',
292
294
  response_type: 'json',
293
- start_time: Time.new(2018, 1, 1, 0, 0, 30, 0),
294
- end_time: Time.new(2018, 1, 1, 0, 0, 32, 0),
295
+ timing: 2000,
296
+ time: Time.new(2018, 1, 1, 0, 0, 30, 0),
295
297
  groups: { db: 55, view: 11 },
296
298
  ),
297
299
  )
@@ -332,8 +334,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
332
334
  queue: 'emails',
333
335
  error_count: 2,
334
336
  groups: { redis: 131, sql: 421 },
335
- start_time: Time.new(2018, 1, 1, 0, 49, 0, 0),
336
- end_time: Time.new(2018, 1, 1, 0, 50, 0, 0),
337
+ timing: 60000,
338
+ time: Time.new(2018, 1, 1, 0, 49, 0, 0),
337
339
  ),
338
340
  )
339
341
  subject.notify(
@@ -341,8 +343,8 @@ RSpec.describe Airbrake::PerformanceNotifier do
341
343
  queue: 'emails',
342
344
  error_count: 3,
343
345
  groups: { redis: 131, sql: 421 },
344
- start_time: Time.new(2018, 1, 1, 0, 49, 0, 0),
345
- end_time: Time.new(2018, 1, 1, 0, 50, 0, 0),
346
+ timing: 60000,
347
+ time: Time.new(2018, 1, 1, 0, 49, 0, 0),
346
348
  ),
347
349
  )
348
350
  subject.close
@@ -381,7 +383,7 @@ RSpec.describe Airbrake::PerformanceNotifier do
381
383
  method: 'GET',
382
384
  route: '/foo',
383
385
  status_code: 200,
384
- start_time: Time.new(2018, 1, 1, 0, 49, 0, 0),
386
+ timing: 123,
385
387
  ),
386
388
  )
387
389
  subject.close
@@ -392,7 +394,7 @@ RSpec.describe Airbrake::PerformanceNotifier do
392
394
 
393
395
  it "checks performance stat configuration" do
394
396
  request = Airbrake::Request.new(
395
- method: 'GET', route: '/foo', status_code: 200, start_time: Time.new,
397
+ method: 'GET', route: '/foo', status_code: 200, timing: 123,
396
398
  )
397
399
  expect(Airbrake::Config.instance).to receive(:check_performance_options)
398
400
  .with(request).and_return(Airbrake::Promise.new)
@@ -408,7 +410,7 @@ RSpec.describe Airbrake::PerformanceNotifier do
408
410
  method: 'POST',
409
411
  route: '/foo',
410
412
  status_code: 200,
411
- start_time: Time.new,
413
+ timing: 123,
412
414
  ),
413
415
  )
414
416
  subject.close
@@ -445,7 +447,7 @@ RSpec.describe Airbrake::PerformanceNotifier do
445
447
  method: 'GET',
446
448
  route: '/foo',
447
449
  status_code: 200,
448
- start_time: Time.new(2018, 1, 1, 0, 49, 0, 0),
450
+ timing: 123,
449
451
  ),
450
452
  )
451
453
 
@@ -454,7 +456,7 @@ RSpec.describe Airbrake::PerformanceNotifier do
454
456
  method: 'POST',
455
457
  route: '/foo',
456
458
  query: 'SELECT * FROM things',
457
- start_time: Time.new(2018, 1, 1, 0, 49, 0, 0),
459
+ timing: 123,
458
460
  ),
459
461
  )
460
462
 
@@ -474,7 +476,7 @@ RSpec.describe Airbrake::PerformanceNotifier do
474
476
  method: 'GET',
475
477
  route: '/foo',
476
478
  status_code: 200,
477
- start_time: Time.new(2018, 1, 1, 0, 49, 0, 0),
479
+ timing: 1,
478
480
  ),
479
481
  )
480
482
  subject.close
@@ -488,13 +490,29 @@ RSpec.describe Airbrake::PerformanceNotifier do
488
490
  method: 'POST',
489
491
  route: '/foo',
490
492
  query: 'SELECT * FROM things',
491
- start_time: Time.new(2018, 1, 1, 0, 49, 0, 0),
493
+ timing: 1,
492
494
  ),
493
495
  )
494
496
  subject.close
495
497
 
496
498
  expect(a_request(:put, queries)).not_to have_been_made
497
499
  end
500
+
501
+ it "returns a rejected promise" do
502
+ promise = subject.notify(
503
+ Airbrake::Query.new(
504
+ method: 'POST',
505
+ route: '/foo',
506
+ query: 'SELECT * FROM things',
507
+ timing: 1,
508
+ ),
509
+ )
510
+ subject.close
511
+
512
+ expect(promise.value).to eq(
513
+ 'error' => 'Airbrake::Query was ignored by a filter',
514
+ )
515
+ end
498
516
  end
499
517
 
500
518
  context "when a filter that modifies payload was defined" do
@@ -510,7 +528,7 @@ RSpec.describe Airbrake::PerformanceNotifier do
510
528
  method: 'POST',
511
529
  route: '/foo',
512
530
  query: 'SELECT * FROM things',
513
- start_time: Time.new(2018, 1, 1, 0, 49, 0, 0),
531
+ timing: 123,
514
532
  ),
515
533
  )
516
534
  subject.close
@@ -522,6 +540,49 @@ RSpec.describe Airbrake::PerformanceNotifier do
522
540
  ).to have_been_made
523
541
  end
524
542
  end
543
+
544
+ context "when :start_time is specified (deprecated)" do
545
+ before do
546
+ allow(Kernel).to receive(:warn)
547
+ end
548
+
549
+ it "uses the value of :start_time to update stat" do
550
+ subject.notify(
551
+ Airbrake::Query.new(
552
+ method: 'POST',
553
+ route: '/foo',
554
+ query: 'SELECT * FROM things',
555
+ start_time: Time.new(2018, 1, 1, 0, 49, 0, 0),
556
+ end_time: Time.new(2018, 1, 1, 0, 50, 0, 0),
557
+ ),
558
+ )
559
+ subject.close
560
+
561
+ expect(
562
+ a_request(:put, queries).with(
563
+ body: /"count":1,"sum":60000.0,"sumsq":3600000000.0/,
564
+ ),
565
+ ).to have_been_made
566
+ end
567
+ end
568
+
569
+ context "when provided :timing is zero" do
570
+ it "doesn't notify" do
571
+ queue = Airbrake::Queue.new(queue: 'bananas', error_count: 0, timing: 0)
572
+ subject.notify(queue)
573
+ subject.close
574
+
575
+ expect(a_request(:put, queues)).not_to have_been_made
576
+ end
577
+
578
+ it "returns a rejected promise" do
579
+ queue = Airbrake::Queue.new(queue: 'bananas', error_count: 0, timing: 0)
580
+ promise = subject.notify(queue)
581
+ subject.close
582
+
583
+ expect(promise.value).to eq('error' => ':timing cannot be zero')
584
+ end
585
+ end
525
586
  end
526
587
 
527
588
  describe "#notify_sync" do
@@ -531,7 +592,7 @@ RSpec.describe Airbrake::PerformanceNotifier do
531
592
  method: 'POST',
532
593
  route: '/foo',
533
594
  query: 'SELECT * FROM things',
534
- start_time: Time.new(2018, 1, 1, 0, 49, 0, 0),
595
+ timing: 123,
535
596
  ),
536
597
  )
537
598
 
@@ -560,7 +621,7 @@ RSpec.describe Airbrake::PerformanceNotifier do
560
621
  method: 'POST',
561
622
  route: '/foo',
562
623
  query: 'SELECT * FROM things',
563
- start_time: Time.new(2018, 1, 1, 0, 49, 0, 0),
624
+ timing: 123,
564
625
  ),
565
626
  )
566
627
  subject.close
@@ -591,7 +652,7 @@ RSpec.describe Airbrake::PerformanceNotifier do
591
652
  method: 'POST',
592
653
  route: '/foo',
593
654
  status_code: 200,
594
- start_time: Time.new(2018, 1, 1, 0, 49, 0, 0),
655
+ timing: 123,
595
656
  ),
596
657
  )
597
658
  subject.close
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: 4.10.1
4
+ version: 4.12.0
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: 2019-12-12 00:00:00.000000000 Z
11
+ date: 2020-01-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rbtree3