airbrake-ruby 2.8.3 → 2.9.0

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: 3f2a54611d3b5e6242dafa75f513058acf49d48b
4
- data.tar.gz: 14871f5c3d358fbfa75718c8e1f88f3905657904
3
+ metadata.gz: 5a9ac80f76081013e1f710824cbe72291d26bda5
4
+ data.tar.gz: a665035c27cdbbdea9cb7bef43b43931be5266f9
5
5
  SHA512:
6
- metadata.gz: e849545f4261e4d1136f3de74a2f0179709c5895f2ab52446c64538e4bcf0201b2d747d3d1e5df7730849148f13748dc6f4b6d227a0b30c548359013d58dd7e3
7
- data.tar.gz: bf4085ed3db6b3e355a3cbc3b375d47dc74090fa70e20718fb9dac3e701ce3b9d05bf53840193b6fc5b4f75cdbd71916354b0ac0e09a872357bf7b3d5492be9c
6
+ metadata.gz: bc673d309a343d6b15d533e1feb4e202fcc1bb3ca31f2ef79e9af257fedd831614874c0efcfd32b88155a28448cd04affa4117567843972f594fe7a4dda77a80
7
+ data.tar.gz: 9e92da2e216c266de65d35c309eed96791eadd6f7e89aca0ebd9e643e49630970b0c41e7da94f15e31cafd65c7f6131668b1a7b41174a44caad94a15eaf665a9
@@ -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
- return false if @closed
83
+ @mutex.synchronize do
84
+ return false if @closed
84
85
 
85
- if @pid != Process.pid && @workers.list.empty?
86
- @pid = Process.pid
87
- spawn_workers
88
- end
86
+ if @pid != Process.pid && @workers.list.empty?
87
+ @pid = Process.pid
88
+ spawn_workers
89
+ end
89
90
 
90
- !@closed && @workers.list.any?
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
@@ -5,7 +5,7 @@ module Airbrake
5
5
  class GemRootFilter
6
6
  ##
7
7
  # @return [String]
8
- GEM_ROOT_LABEL = '[GEM_ROOT]'.freeze
8
+ GEM_ROOT_LABEL = '/GEM_ROOT'.freeze
9
9
 
10
10
  ##
11
11
  # @return [Integer]
@@ -5,7 +5,7 @@ module Airbrake
5
5
  class RootDirectoryFilter
6
6
  ##
7
7
  # @return [String]
8
- PROJECT_ROOT_LABEL = '[PROJECT_ROOT]'.freeze
8
+ PROJECT_ROOT_LABEL = '/PROJECT_ROOT'.freeze
9
9
 
10
10
  ##
11
11
  # @return [Integer]
@@ -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
@@ -4,5 +4,5 @@
4
4
  module Airbrake
5
5
  ##
6
6
  # @return [String] the library version
7
- AIRBRAKE_RUBY_VERSION = '2.8.3'.freeze
7
+ AIRBRAKE_RUBY_VERSION = '2.9.0'.freeze
8
8
  end
@@ -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":"\[PROJECT_ROOT\]/spec/airbrake_spec.rb","line":\d+,"function":"[\w/\s\(\)<>]+","code".+},
85
- {"file":"\[GEM_ROOT\]/gems/rspec-core-.+/.+","line":\d+,"function":"[\w/\s\(\)<>]+".+
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(3)
166
+ expect(filters.size).to eq(4)
167
167
 
168
168
  described_class.add_filter {}
169
169
 
170
- expect(filters.size).to eq(4)
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: "[GEM_ROOT]/gems/rspec-core-3.3.2/lib/rspec/core/configuration.rb" },
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: "[GEM_ROOT]/gems/rspec-core-3.3.2/exe/rspec" }
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: "[PROJECT_ROOT]/gems/rspec-core-3.3.2/lib/rspec/core/configuration.rb " },
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: "[PROJECT_ROOT]/gems/rspec-core-3.3.2/exe/rspec" }
31
+ { file: "/PROJECT_ROOT/gems/rspec-core-3.3.2/exe/rspec" }
32
32
  ]
33
33
  )
34
34
  )
@@ -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":"\[PROJECT_ROOT\]/airbrake/ruby/spec/airbrake_spec.+|)
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.8.3
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-03-12 00:00:00.000000000 Z
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