airbrake-ruby 2.8.3 → 2.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/airbrake-ruby.rb +50 -0
- data/lib/airbrake-ruby/async_sender.rb +8 -6
- data/lib/airbrake-ruby/filters/context_filter.rb +28 -0
- data/lib/airbrake-ruby/filters/gem_root_filter.rb +1 -1
- data/lib/airbrake-ruby/filters/root_directory_filter.rb +1 -1
- data/lib/airbrake-ruby/notifier.rb +12 -0
- data/lib/airbrake-ruby/version.rb +1 -1
- data/spec/airbrake_spec.rb +8 -4
- data/spec/filters/context_filter_spec.rb +27 -0
- data/spec/filters/gem_root_filter_spec.rb +2 -2
- data/spec/filters/root_directory_filter_spec.rb +2 -2
- data/spec/notifier_spec.rb +11 -0
- data/spec/notifier_spec/options_spec.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5a9ac80f76081013e1f710824cbe72291d26bda5
|
4
|
+
data.tar.gz: a665035c27cdbbdea9cb7bef43b43931be5266f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bc673d309a343d6b15d533e1feb4e202fcc1bb3ca31f2ef79e9af257fedd831614874c0efcfd32b88155a28448cd04affa4117567843972f594fe7a4dda77a80
|
7
|
+
data.tar.gz: 9e92da2e216c266de65d35c309eed96791eadd6f7e89aca0ebd9e643e49630970b0c41e7da94f15e31cafd65c7f6131668b1a7b41174a44caad94a15eaf665a9
|
data/lib/airbrake-ruby.rb
CHANGED
@@ -23,6 +23,7 @@ require 'airbrake-ruby/filters/gem_root_filter'
|
|
23
23
|
require 'airbrake-ruby/filters/system_exit_filter'
|
24
24
|
require 'airbrake-ruby/filters/root_directory_filter'
|
25
25
|
require 'airbrake-ruby/filters/thread_filter'
|
26
|
+
require 'airbrake-ruby/filters/context_filter'
|
26
27
|
require 'airbrake-ruby/filter_chain'
|
27
28
|
require 'airbrake-ruby/notifier'
|
28
29
|
require 'airbrake-ruby/code_hunk'
|
@@ -268,5 +269,54 @@ module Airbrake
|
|
268
269
|
def create_deploy(deploy_params)
|
269
270
|
@notifiers[:default].create_deploy(deploy_params)
|
270
271
|
end
|
272
|
+
|
273
|
+
##
|
274
|
+
# Merges +context+ with the current context.
|
275
|
+
#
|
276
|
+
# The context will be attached to the notice object upon a notify call and
|
277
|
+
# cleared after it's attached. The context data is attached to the
|
278
|
+
# `params/airbrake_context` key.
|
279
|
+
#
|
280
|
+
# @example
|
281
|
+
# class MerryGrocer
|
282
|
+
# def load_fruits(fruits)
|
283
|
+
# Airbrake.merge_context(fruits: fruits)
|
284
|
+
# end
|
285
|
+
#
|
286
|
+
# def deliver_fruits
|
287
|
+
# Airbrake.notify('fruitception')
|
288
|
+
# end
|
289
|
+
#
|
290
|
+
# def load_veggies
|
291
|
+
# Airbrake.merge_context(veggies: veggies)
|
292
|
+
# end
|
293
|
+
#
|
294
|
+
# def deliver_veggies
|
295
|
+
# Airbrake.notify('veggieboom!')
|
296
|
+
# end
|
297
|
+
# end
|
298
|
+
#
|
299
|
+
# grocer = MerryGrocer.new
|
300
|
+
#
|
301
|
+
# # Load some fruits to the context.
|
302
|
+
# grocer.load_fruits(%w(mango banana apple))
|
303
|
+
#
|
304
|
+
# # Deliver the fruits. Note that we are not passing anything,
|
305
|
+
# # `deliver_fruits` knows that we loaded something.
|
306
|
+
# grocer.deliver_fruits
|
307
|
+
#
|
308
|
+
# # Load some vegetables and deliver them to Airbrake. Note that the
|
309
|
+
# # fruits have been delivered and therefore the grocer doesn't have them
|
310
|
+
# # anymore. We merge veggies with the new context.
|
311
|
+
# grocer.load_veggies(%w(cabbage carrot onion))
|
312
|
+
# grocer.deliver_veggies
|
313
|
+
#
|
314
|
+
# # The context is empty again, feel free to load more.
|
315
|
+
#
|
316
|
+
# @param [Hash{Symbol=>Object}] context
|
317
|
+
# @return [void]
|
318
|
+
def merge_context(context)
|
319
|
+
@notifiers[:default].merge_context(context)
|
320
|
+
end
|
271
321
|
end
|
272
322
|
end
|
@@ -80,14 +80,16 @@ module Airbrake
|
|
80
80
|
# @return [Boolean] true if an instance wasn't closed, but has no workers
|
81
81
|
# @see https://goo.gl/oydz8h Example of at_exit that prevents exit
|
82
82
|
def has_workers?
|
83
|
-
|
83
|
+
@mutex.synchronize do
|
84
|
+
return false if @closed
|
84
85
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
86
|
+
if @pid != Process.pid && @workers.list.empty?
|
87
|
+
@pid = Process.pid
|
88
|
+
spawn_workers
|
89
|
+
end
|
89
90
|
|
90
|
-
|
91
|
+
!@closed && @workers.list.any?
|
92
|
+
end
|
91
93
|
end
|
92
94
|
|
93
95
|
private
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Airbrake
|
2
|
+
module Filters
|
3
|
+
# Adds user context to the notice object. Clears the context after it's
|
4
|
+
# attached.
|
5
|
+
#
|
6
|
+
# @api private
|
7
|
+
# @since v2.9.0
|
8
|
+
class ContextFilter
|
9
|
+
# @return [Integer]
|
10
|
+
attr_reader :weight
|
11
|
+
|
12
|
+
def initialize(context)
|
13
|
+
@context = context
|
14
|
+
@weight = 119
|
15
|
+
@mutex = Mutex.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def call(notice)
|
19
|
+
@mutex.synchronize do
|
20
|
+
return if @context.empty?
|
21
|
+
|
22
|
+
notice[:params][:airbrake_context] = @context.dup
|
23
|
+
@context.clear
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -31,6 +31,8 @@ module Airbrake
|
|
31
31
|
|
32
32
|
raise Airbrake::Error, @config.validation_error_message unless @config.valid?
|
33
33
|
|
34
|
+
@context = {}
|
35
|
+
|
34
36
|
@filter_chain = FilterChain.new
|
35
37
|
add_default_filters
|
36
38
|
|
@@ -98,6 +100,12 @@ module Airbrake
|
|
98
100
|
@config.valid?
|
99
101
|
end
|
100
102
|
|
103
|
+
##
|
104
|
+
# @macro see_public_api_method
|
105
|
+
def merge_context(context)
|
106
|
+
@context.merge!(context)
|
107
|
+
end
|
108
|
+
|
101
109
|
private
|
102
110
|
|
103
111
|
def convert_to_exception(ex)
|
@@ -162,6 +170,8 @@ module Airbrake
|
|
162
170
|
)
|
163
171
|
end
|
164
172
|
|
173
|
+
@filter_chain.add_filter(Airbrake::Filters::ContextFilter.new(@context))
|
174
|
+
|
165
175
|
return unless (root_directory = @config.root_directory)
|
166
176
|
@filter_chain.add_filter(
|
167
177
|
Airbrake::Filters::RootDirectoryFilter.new(root_directory)
|
@@ -190,5 +200,7 @@ module Airbrake
|
|
190
200
|
def configured?
|
191
201
|
false
|
192
202
|
end
|
203
|
+
|
204
|
+
def merge_context(_context); end
|
193
205
|
end
|
194
206
|
end
|
data/spec/airbrake_spec.rb
CHANGED
@@ -81,8 +81,8 @@ RSpec.describe Airbrake do
|
|
81
81
|
# rubocop:disable Metrics/LineLength
|
82
82
|
expected_body = %r|
|
83
83
|
{"errors":\[{"type":"RuntimeError","message":"bingo","backtrace":\[
|
84
|
-
{"file":"
|
85
|
-
{"file":"
|
84
|
+
{"file":"/PROJECT_ROOT/spec/airbrake_spec.rb","line":\d+,"function":"[\w/\s\(\)<>]+","code".+},
|
85
|
+
{"file":"/GEM_ROOT/gems/rspec-core-.+/.+","line":\d+,"function":"[\w/\s\(\)<>]+".+
|
86
86
|
|x
|
87
87
|
# rubocop:enable Metrics/LineLength
|
88
88
|
|
@@ -163,11 +163,11 @@ RSpec.describe Airbrake do
|
|
163
163
|
filter_chain = notifier.instance_variable_get(:@filter_chain)
|
164
164
|
filters = filter_chain.instance_variable_get(:@filters)
|
165
165
|
|
166
|
-
expect(filters.size).to eq(
|
166
|
+
expect(filters.size).to eq(4)
|
167
167
|
|
168
168
|
described_class.add_filter {}
|
169
169
|
|
170
|
-
expect(filters.size).to eq(
|
170
|
+
expect(filters.size).to eq(5)
|
171
171
|
expect(filters.last).to be_a(Proc)
|
172
172
|
end
|
173
173
|
end
|
@@ -175,4 +175,8 @@ RSpec.describe Airbrake do
|
|
175
175
|
describe ".build_notice" do
|
176
176
|
include_examples 'non-configured notifier handling', :build_notice
|
177
177
|
end
|
178
|
+
|
179
|
+
describe ".merge_context" do
|
180
|
+
include_examples 'non-configured notifier handling', :merge_context
|
181
|
+
end
|
178
182
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Airbrake::Filters::ContextFilter do
|
4
|
+
let(:notice) do
|
5
|
+
Airbrake::Notice.new(Airbrake::Config.new, AirbrakeTestError.new)
|
6
|
+
end
|
7
|
+
|
8
|
+
context "when the current context is empty" do
|
9
|
+
it "doesn't merge anything with params" do
|
10
|
+
described_class.new({}).call(notice)
|
11
|
+
expect(notice[:params]).to be_empty
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context "when the current context has some data" do
|
16
|
+
it "merges the data with params" do
|
17
|
+
described_class.new(apples: 'oranges').call(notice)
|
18
|
+
expect(notice[:params]).to eq(airbrake_context: { apples: 'oranges' })
|
19
|
+
end
|
20
|
+
|
21
|
+
it "clears the data from the provided context" do
|
22
|
+
context = { apples: 'oranges' }
|
23
|
+
described_class.new(context).call(notice)
|
24
|
+
expect(context).to be_empty
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -28,9 +28,9 @@ RSpec.describe Airbrake::Filters::GemRootFilter do
|
|
28
28
|
eq(
|
29
29
|
[
|
30
30
|
{ file: "/home/kyrylo/code/airbrake/ruby/spec/spec_helper.rb" },
|
31
|
-
{ file: "
|
31
|
+
{ file: "/GEM_ROOT/gems/rspec-core-3.3.2/lib/rspec/core/configuration.rb" },
|
32
32
|
{ file: "/opt/rubies/ruby-2.2.2/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb" },
|
33
|
-
{ file: "
|
33
|
+
{ file: "/GEM_ROOT/gems/rspec-core-3.3.2/exe/rspec" }
|
34
34
|
]
|
35
35
|
)
|
36
36
|
)
|
@@ -26,9 +26,9 @@ RSpec.describe Airbrake::Filters::RootDirectoryFilter do
|
|
26
26
|
eq(
|
27
27
|
[
|
28
28
|
{ file: "/home/kyrylo/code/airbrake/ruby/spec/spec_helper.rb" },
|
29
|
-
{ file: "
|
29
|
+
{ file: "/PROJECT_ROOT/gems/rspec-core-3.3.2/lib/rspec/core/configuration.rb " },
|
30
30
|
{ file: "/opt/rubies/ruby-2.2.2/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb" },
|
31
|
-
{ file: "
|
31
|
+
{ file: "/PROJECT_ROOT/gems/rspec-core-3.3.2/exe/rspec" }
|
32
32
|
]
|
33
33
|
)
|
34
34
|
)
|
data/spec/notifier_spec.rb
CHANGED
@@ -614,4 +614,15 @@ RSpec.describe Airbrake::Notifier do
|
|
614
614
|
subject { described_class.new(airbrake_params) }
|
615
615
|
it { is_expected.to be_configured }
|
616
616
|
end
|
617
|
+
|
618
|
+
describe "#merge_context" do
|
619
|
+
it "merges the provided context with the notice object" do
|
620
|
+
@airbrake.merge_context(apples: 'oranges')
|
621
|
+
@airbrake.notify_sync('oops')
|
622
|
+
expect(
|
623
|
+
a_request(:post, endpoint).
|
624
|
+
with(body: /"params":{"airbrake_context":{"apples":"oranges"}/)
|
625
|
+
).to have_been_made.once
|
626
|
+
end
|
627
|
+
end
|
617
628
|
end
|
@@ -75,7 +75,7 @@ RSpec.describe Airbrake::Notifier do
|
|
75
75
|
|
76
76
|
expect(
|
77
77
|
a_request(:post, endpoint).
|
78
|
-
with(body: %r|{"file":"
|
78
|
+
with(body: %r|{"file":"/PROJECT_ROOT/airbrake/ruby/spec/airbrake_spec.+|)
|
79
79
|
).to have_been_made.once
|
80
80
|
end
|
81
81
|
|
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: 2.
|
4
|
+
version: 2.9.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: 2018-
|
11
|
+
date: 2018-04-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -123,6 +123,7 @@ files:
|
|
123
123
|
- lib/airbrake-ruby/config/validator.rb
|
124
124
|
- lib/airbrake-ruby/file_cache.rb
|
125
125
|
- lib/airbrake-ruby/filter_chain.rb
|
126
|
+
- lib/airbrake-ruby/filters/context_filter.rb
|
126
127
|
- lib/airbrake-ruby/filters/gem_root_filter.rb
|
127
128
|
- lib/airbrake-ruby/filters/keys_blacklist.rb
|
128
129
|
- lib/airbrake-ruby/filters/keys_filter.rb
|
@@ -146,6 +147,7 @@ files:
|
|
146
147
|
- spec/config_spec.rb
|
147
148
|
- spec/file_cache.rb
|
148
149
|
- spec/filter_chain_spec.rb
|
150
|
+
- spec/filters/context_filter_spec.rb
|
149
151
|
- spec/filters/gem_root_filter_spec.rb
|
150
152
|
- spec/filters/keys_blacklist_spec.rb
|
151
153
|
- spec/filters/keys_whitelist_spec.rb
|
@@ -198,6 +200,7 @@ test_files:
|
|
198
200
|
- spec/filters/keys_whitelist_spec.rb
|
199
201
|
- spec/filters/system_exit_filter_spec.rb
|
200
202
|
- spec/filters/thread_filter_spec.rb
|
203
|
+
- spec/filters/context_filter_spec.rb
|
201
204
|
- spec/filters/keys_blacklist_spec.rb
|
202
205
|
- spec/filters/gem_root_filter_spec.rb
|
203
206
|
- spec/spec_helper.rb
|