airbrake-ruby 4.8.0-java → 4.9.0-java

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
  SHA256:
3
- metadata.gz: 775c69e72c377a245982fca5bef3460af77b6c37d82988432fc09f2820e01fc6
4
- data.tar.gz: 83493c7a39f6eea49668f7c94fc202c90d55efcc1d4822864a70cca03c96134f
3
+ metadata.gz: 1e05d33daf76111bb1a55538d29cba82f1ac99c97578ee07843af8b88750b7a5
4
+ data.tar.gz: e7e11e55e646e58d8740a7ce6f97e0b7f3f27437f732c6d348be24df409a3ad2
5
5
  SHA512:
6
- metadata.gz: 3e99d7a4dbca2de4e45a63d0991856e68a6d4250979b2989208597ba65f6f6559aab001702cd0d2140902b15b3f87bb6c75a21b3c9c97a272f68b4d62922a4e8
7
- data.tar.gz: 030edc9303bd0f1042a6aa3f3ec5b672ab58598fee90a71e6d7f6a6fed84716d2043afab9edf46b3bdd6ee9939ef6b979ad78dc37575be774663ac84e8af73a7
6
+ metadata.gz: f8b47d08818f4dec1b1d3ed5e381e10392e1da33677894e8a10d2e07c9ede4b1adffeab060a931b13da9f26f4d6f9f5ff25b9ec6beba677a674528260246fd0c
7
+ data.tar.gz: 4a77aa66088214bddeab8b4c7eac2c82a3f1f7354fe6d37c8e679c4e46a16efde2c753ee3fb02397612f0ea1c93e8430968057aa70b45a6e0a97658158346d46
@@ -9,6 +9,8 @@ require 'time'
9
9
  require 'airbrake-ruby/version'
10
10
  require 'airbrake-ruby/loggable'
11
11
  require 'airbrake-ruby/stashable'
12
+ require 'airbrake-ruby/mergeable'
13
+ require 'airbrake-ruby/grouppable'
12
14
  require 'airbrake-ruby/config'
13
15
  require 'airbrake-ruby/config/validator'
14
16
  require 'airbrake-ruby/promise'
@@ -52,6 +54,7 @@ require 'airbrake-ruby/performance_breakdown'
52
54
  require 'airbrake-ruby/benchmark'
53
55
  require 'airbrake-ruby/monotonic_time'
54
56
  require 'airbrake-ruby/timed_trace'
57
+ require 'airbrake-ruby/queue'
55
58
 
56
59
  # Airbrake is a thin wrapper around instances of the notifier classes (such as
57
60
  # notice, performance & deploy notifiers). It creates a way to access them via a
@@ -69,6 +72,7 @@ require 'airbrake-ruby/timed_trace'
69
72
  #
70
73
  # @since v1.0.0
71
74
  # @api public
75
+ # rubocop:disable Metrics/ModuleLength
72
76
  module Airbrake
73
77
  # The general error that this library uses when it wants to raise.
74
78
  Error = Class.new(StandardError)
@@ -423,6 +427,31 @@ module Airbrake
423
427
  performance_notifier.notify(performance_breakdown)
424
428
  end
425
429
 
430
+ # Increments statistics of a certain queue (worker).
431
+ #
432
+ # @example
433
+ # Airbrake.notify_queue(
434
+ # queue: 'emails',
435
+ # error_count: 1,
436
+ # groups: { redis: 24.0, sql: 0.4 } # ms
437
+ # )
438
+ #
439
+ # @param [Hash{Symbol=>Object}] queue_info
440
+ # @option queue_info [String] :queue The name of the queue/worker
441
+ # @option queue_info [Integer] :error_count How many times this worker
442
+ # failed
443
+ # @option queue_info [Array<Hash{Symbol=>Float}>] :groups Where the job
444
+ # spent its time
445
+ # @param [Hash] stash What needs to be appeneded to the stash, so it's
446
+ # available in filters
447
+ # @return [void]
448
+ # @since v4.9.0
449
+ def notify_queue(queue_info, stash = {})
450
+ queue = Queue.new(queue_info)
451
+ queue.stash.merge!(stash)
452
+ performance_notifier.notify(queue)
453
+ end
454
+
426
455
  # Runs a callback before {.notify_request} or {.notify_query} kicks in. This
427
456
  # is useful if you want to ignore specific resources or filter the data the
428
457
  # resource contains.
@@ -513,3 +542,4 @@ module Airbrake
513
542
  end
514
543
  end
515
544
  end
545
+ # rubocop:enable Metrics/ModuleLength
@@ -0,0 +1,12 @@
1
+ module Airbrake
2
+ # Grouppable adds the `#groups` method, so that we don't need to define it in
3
+ # all of performance models every time we add a model without groups.
4
+ #
5
+ # @since 4.9.0
6
+ # @api private
7
+ module Grouppable
8
+ def groups
9
+ {}
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module Airbrake
2
+ # Mergeable adds the `#merge` method, so that we don't need to define it in
3
+ # all of performance models every time we add a model.
4
+ #
5
+ # @since 4.9.0
6
+ # @api private
7
+ module Mergeable
8
+ def merge(_other)
9
+ nil
10
+ end
11
+ end
12
+ end
@@ -12,6 +12,7 @@ module Airbrake
12
12
  include HashKeyable
13
13
  include Ignorable
14
14
  include Stashable
15
+ include Mergeable
15
16
 
16
17
  def initialize(
17
18
  method:,
@@ -61,7 +61,12 @@ module Airbrake
61
61
  private
62
62
 
63
63
  def update_payload(resource)
64
- @payload[resource] ||= { total: Airbrake::Stat.new }
64
+ if (total_stat = @payload[resource])
65
+ @payload.key(total_stat).merge(resource)
66
+ else
67
+ @payload[resource] = { total: Airbrake::Stat.new }
68
+ end
69
+
65
70
  @payload[resource][:total].increment(resource.start_time, resource.end_time)
66
71
 
67
72
  resource.groups.each do |name, ms|
@@ -11,6 +11,8 @@ module Airbrake
11
11
  include HashKeyable
12
12
  include Ignorable
13
13
  include Stashable
14
+ include Mergeable
15
+ include Grouppable
14
16
 
15
17
  def initialize(
16
18
  method:,
@@ -34,10 +36,6 @@ module Airbrake
34
36
  'queries'
35
37
  end
36
38
 
37
- def groups
38
- {}
39
- end
40
-
41
39
  def to_h
42
40
  {
43
41
  'method' => method,
@@ -0,0 +1,52 @@
1
+ module Airbrake
2
+ # Queue represents a queue (worker).
3
+ #
4
+ # @see Airbrake.notify_queue
5
+ # @api public
6
+ # @since v4.9.0
7
+ # rubocop:disable Metrics/BlockLength
8
+ Queue = Struct.new(:queue, :error_count, :groups, :start_time, :end_time) do
9
+ include HashKeyable
10
+ include Ignorable
11
+ include Stashable
12
+
13
+ def initialize(
14
+ queue:,
15
+ error_count:,
16
+ groups: {},
17
+ start_time: Time.now,
18
+ end_time: Time.now
19
+ )
20
+ @start_time_utc = TimeTruncate.utc_truncate_minutes(start_time)
21
+ super(queue, error_count, groups, start_time, end_time)
22
+ end
23
+
24
+ def destination
25
+ 'queues-stats'
26
+ end
27
+
28
+ def cargo
29
+ 'queues'
30
+ end
31
+
32
+ def to_h
33
+ {
34
+ 'queue' => queue,
35
+ 'errorCount' => error_count,
36
+ 'time' => @start_time_utc
37
+ }
38
+ end
39
+
40
+ def hash
41
+ {
42
+ 'queue' => queue,
43
+ 'time' => @start_time_utc
44
+ }.hash
45
+ end
46
+
47
+ def merge(other)
48
+ self.error_count += other.error_count
49
+ end
50
+ end
51
+ # rubocop:enable Metrics/BlockLength
52
+ end
@@ -9,6 +9,8 @@ module Airbrake
9
9
  include HashKeyable
10
10
  include Ignorable
11
11
  include Stashable
12
+ include Mergeable
13
+ include Grouppable
12
14
 
13
15
  def initialize(
14
16
  method:,
@@ -29,10 +31,6 @@ module Airbrake
29
31
  'routes'
30
32
  end
31
33
 
32
- def groups
33
- {}
34
- end
35
-
36
34
  def to_h
37
35
  {
38
36
  'method' => method,
@@ -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.8.0'.freeze
5
+ AIRBRAKE_RUBY_VERSION = '4.9.0'.freeze
6
6
  end
@@ -303,6 +303,37 @@ RSpec.describe Airbrake do
303
303
  end
304
304
  end
305
305
 
306
+ describe "#notify_queue" do
307
+ context "when :stash key is not provided" do
308
+ it "doesn't add anything to the stash of the queue" do
309
+ expect(described_class.performance_notifier).to receive(:notify) do |queue|
310
+ expect(queue.stash).to be_empty
311
+ end
312
+
313
+ described_class.notify_queue(
314
+ queue: 'bananas',
315
+ error_count: 10
316
+ )
317
+ end
318
+ end
319
+
320
+ context "when :stash key is provided" do
321
+ it "adds the value as the stash of the queue" do
322
+ expect(described_class.performance_notifier).to receive(:notify) do |queue|
323
+ expect(queue.stash).to eq(request_id: 1)
324
+ end
325
+
326
+ described_class.notify_queue(
327
+ {
328
+ queue: 'bananas',
329
+ error_count: 10
330
+ },
331
+ request_id: 1
332
+ )
333
+ end
334
+ end
335
+ end
336
+
306
337
  describe ".performance_notifier" do
307
338
  it "returns a performance notifier" do
308
339
  expect(described_class.performance_notifier)
@@ -2,11 +2,13 @@ RSpec.describe Airbrake::PerformanceNotifier do
2
2
  let(:routes) { 'https://api.airbrake.io/api/v5/projects/1/routes-stats' }
3
3
  let(:queries) { 'https://api.airbrake.io/api/v5/projects/1/queries-stats' }
4
4
  let(:breakdowns) { 'https://api.airbrake.io/api/v5/projects/1/routes-breakdowns' }
5
+ let(:queues) { 'https://api.airbrake.io/api/v5/projects/1/queues-stats' }
5
6
 
6
7
  before do
7
8
  stub_request(:put, routes).to_return(status: 200, body: '')
8
9
  stub_request(:put, queries).to_return(status: 200, body: '')
9
10
  stub_request(:put, breakdowns).to_return(status: 200, body: '')
11
+ stub_request(:put, queues).to_return(status: 200, body: '')
10
12
 
11
13
  Airbrake::Config.instance = Airbrake::Config.new(
12
14
  project_id: 1,
@@ -120,6 +122,46 @@ RSpec.describe Airbrake::PerformanceNotifier do
120
122
  ).to have_been_made
121
123
  end
122
124
 
125
+ it "sends full queue" do
126
+ subject.notify(
127
+ Airbrake::Queue.new(
128
+ queue: 'emails',
129
+ error_count: 2,
130
+ 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)
133
+ )
134
+ )
135
+ subject.close
136
+
137
+ expect(
138
+ a_request(:put, queues).with(body: /
139
+ \A{"queues":\[{
140
+ "queue":"emails",
141
+ "errorCount":2,
142
+ "time":"2018-01-01T00:49:00\+00:00",
143
+ "count":1,
144
+ "sum":60000.0,
145
+ "sumsq":3600000000.0,
146
+ "tdigest":"AAAAAkA0AAAAAAAAAAAAAUdqYAAB",
147
+ "groups":{
148
+ "redis":{
149
+ "count":1,
150
+ "sum":131.0,
151
+ "sumsq":17161.0,
152
+ "tdigest":"AAAAAkA0AAAAAAAAAAAAAUMDAAAB"
153
+ },
154
+ "sql":{
155
+ "count":1,
156
+ "sum":421.0,
157
+ "sumsq":177241.0,
158
+ "tdigest":"AAAAAkA0AAAAAAAAAAAAAUPSgAAB"
159
+ }
160
+ }
161
+ }\]}\z/x)
162
+ ).to have_been_made
163
+ end
164
+
123
165
  it "rounds time to the floor minute" do
124
166
  subject.notify(
125
167
  Airbrake::Request.new(
@@ -284,6 +326,55 @@ RSpec.describe Airbrake::PerformanceNotifier do
284
326
  ).to have_been_made
285
327
  end
286
328
 
329
+ it "groups queues by queue key" do
330
+ subject.notify(
331
+ Airbrake::Queue.new(
332
+ queue: 'emails',
333
+ error_count: 2,
334
+ 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
+ )
338
+ )
339
+ subject.notify(
340
+ Airbrake::Queue.new(
341
+ queue: 'emails',
342
+ error_count: 3,
343
+ 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
+ )
347
+ )
348
+ subject.close
349
+
350
+ expect(
351
+ a_request(:put, queues).with(body: /
352
+ \A{"queues":\[{
353
+ "queue":"emails",
354
+ "errorCount":5,
355
+ "time":"2018-01-01T00:49:00\+00:00",
356
+ "count":2,
357
+ "sum":120000.0,
358
+ "sumsq":7200000000.0,
359
+ "tdigest":"AAAAAkA0AAAAAAAAAAAAAUdqYAAC",
360
+ "groups":{
361
+ "redis":{
362
+ "count":2,
363
+ "sum":262.0,
364
+ "sumsq":34322.0,
365
+ "tdigest":"AAAAAkA0AAAAAAAAAAAAAUMDAAAC"
366
+ },
367
+ "sql":{
368
+ "count":2,
369
+ "sum":842.0,
370
+ "sumsq":354482.0,
371
+ "tdigest":"AAAAAkA0AAAAAAAAAAAAAUPSgAAC"
372
+ }
373
+ }
374
+ }\]}\z/x)
375
+ ).to have_been_made
376
+ end
377
+
287
378
  it "returns a promise" do
288
379
  promise = subject.notify(
289
380
  Airbrake::Request.new(
@@ -0,0 +1,11 @@
1
+ RSpec.describe Airbrake::Queue do
2
+ subject { described_class.new(queue: 'bananas', error_count: 0) }
3
+
4
+ describe "#ignore" do
5
+ it { is_expected.to respond_to(:ignore!) }
6
+ end
7
+
8
+ describe "#stash" do
9
+ it { is_expected.to respond_to(:stash) }
10
+ end
11
+ end
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.8.0
4
+ version: 4.9.0
5
5
  platform: java
6
6
  authors:
7
7
  - Airbrake Technologies, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-23 00:00:00.000000000 Z
11
+ date: 2019-12-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rbtree-jruby
@@ -62,10 +62,12 @@ files:
62
62
  - lib/airbrake-ruby/filters/sql_filter.rb
63
63
  - lib/airbrake-ruby/filters/system_exit_filter.rb
64
64
  - lib/airbrake-ruby/filters/thread_filter.rb
65
+ - lib/airbrake-ruby/grouppable.rb
65
66
  - lib/airbrake-ruby/hash_keyable.rb
66
67
  - lib/airbrake-ruby/ignorable.rb
67
68
  - lib/airbrake-ruby/inspectable.rb
68
69
  - lib/airbrake-ruby/loggable.rb
70
+ - lib/airbrake-ruby/mergeable.rb
69
71
  - lib/airbrake-ruby/monotonic_time.rb
70
72
  - lib/airbrake-ruby/nested_exception.rb
71
73
  - lib/airbrake-ruby/notice.rb
@@ -74,6 +76,7 @@ files:
74
76
  - lib/airbrake-ruby/performance_notifier.rb
75
77
  - lib/airbrake-ruby/promise.rb
76
78
  - lib/airbrake-ruby/query.rb
79
+ - lib/airbrake-ruby/queue.rb
77
80
  - lib/airbrake-ruby/request.rb
78
81
  - lib/airbrake-ruby/response.rb
79
82
  - lib/airbrake-ruby/stashable.rb
@@ -126,6 +129,7 @@ files:
126
129
  - spec/performance_notifier_spec.rb
127
130
  - spec/promise_spec.rb
128
131
  - spec/query_spec.rb
132
+ - spec/queue_spec.rb
129
133
  - spec/request_spec.rb
130
134
  - spec/response_spec.rb
131
135
  - spec/spec_helper.rb
@@ -203,6 +207,7 @@ test_files:
203
207
  - spec/notice_notifier/options_spec.rb
204
208
  - spec/filter_chain_spec.rb
205
209
  - spec/response_spec.rb
210
+ - spec/queue_spec.rb
206
211
  - spec/code_hunk_spec.rb
207
212
  - spec/fixtures/notroot.txt
208
213
  - spec/fixtures/project_root/long_line.txt