airbrake-ruby 2.2.0 → 2.2.1

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: 85e069b4c88a953affccceafa0e250aee3c34367
4
- data.tar.gz: 349b91844712169716c97ba606cdebf6e200e908
3
+ metadata.gz: 21223403ddfa03e2f851d2cb5c4a74130e17840f
4
+ data.tar.gz: ab65e845c6053434813b8bbf0f23edaa80dad44d
5
5
  SHA512:
6
- metadata.gz: d4fdabb0447a4c8b0ca06a45cb8ce371d35805c191253edec1bda3fd0581f60ae5382efbf7d64b56f5845d9444fcd145c73844c6dba94abbcff5b94aad00de8f
7
- data.tar.gz: 4662128a6ad57a91659539296229fe7c0b824a6049abb32f64f9ab883be919a4ced5af56f38a3c768016b4477844eef5db30a600dceca0daa9c9e9822af973ef
6
+ metadata.gz: e045ca4229249ab1cfc9be1b5d94e72bc633134f4e6fbf34a8a3f16068a042823aa5e5fd09d085220de83313ab22c48bb1ab773549b776dbb64fc6a721356bf1
7
+ data.tar.gz: 24117e363c96f7cc6673c63cae41ab5306de8ed61bd03c08d6e011fb52cc17d2bf13d8394a797428ef0428ca151e3188995dff733cdb71d8693a22be1de112ce
@@ -8,48 +8,55 @@ module Airbrake
8
8
  # @since v1.0.0
9
9
  class FilterChain
10
10
  ##
11
- # @return [String] the namespace for filters, which are executed first,
12
- # before any other filters
13
- LIB_NAMESPACE = '#<Airbrake::'.freeze
11
+ # @return [Array<Class>] filters to be executed first
12
+ DEFAULT_FILTERS = [
13
+ Airbrake::Filters::SystemExitFilter,
14
+ Airbrake::Filters::GemRootFilter,
15
+ Airbrake::Filters::ThreadFilter
16
+ ].freeze
14
17
 
15
18
  ##
16
- # Filters to be executed last. By this time all permutations on a notice
17
- # should be done, so the final step is to blacklist/whitelist keys.
18
- # @return [Array<Class>]
19
- KEYS_FILTERS = [
20
- Airbrake::Filters::KeysBlacklist,
21
- Airbrake::Filters::KeysWhitelist
22
- ].freeze
19
+ # @return [Integer]
20
+ DEFAULT_WEIGHT = 0
23
21
 
24
22
  ##
25
23
  # @param [Airbrake::Config] config
26
24
  def initialize(config)
27
25
  @filters = []
28
- @keys_filters = []
29
26
 
30
- [Airbrake::Filters::SystemExitFilter,
31
- Airbrake::Filters::GemRootFilter,
32
- Airbrake::Filters::ThreadFilter].each do |filter|
33
- @filters << filter.new
27
+ DEFAULT_FILTERS.each { |f| add_filter(f.new) }
28
+
29
+ if config.whitelist_keys.any?
30
+ add_filter(
31
+ Airbrake::Filters::KeysWhitelist.new(
32
+ config.logger,
33
+ config.whitelist_keys
34
+ )
35
+ )
34
36
  end
35
37
 
36
- root_directory = config.root_directory
37
- return unless root_directory
38
+ if config.blacklist_keys.any?
39
+ add_filter(
40
+ Airbrake::Filters::KeysBlacklist.new(
41
+ config.logger,
42
+ config.blacklist_keys
43
+ )
44
+ )
45
+ end
38
46
 
39
- @filters << Airbrake::Filters::RootDirectoryFilter.new(root_directory)
47
+ return unless (root_directory = config.root_directory)
48
+ add_filter(Airbrake::Filters::RootDirectoryFilter.new(root_directory))
40
49
  end
41
50
 
42
51
  ##
43
- # Adds a filter to the filter chain.
52
+ # Adds a filter to the filter chain. Sorts filters by weight.
44
53
  #
45
54
  # @param [#call] filter The filter object (proc, class, module, etc)
46
55
  # @return [void]
47
56
  def add_filter(filter)
48
- return @keys_filters << filter if KEYS_FILTERS.include?(filter.class)
49
- return @filters << filter unless filter.to_s.start_with?(LIB_NAMESPACE)
50
-
51
- i = @filters.rindex { |f| f.to_s.start_with?(LIB_NAMESPACE) }
52
- @filters.insert(i + 1, filter) if i
57
+ @filters = (@filters << filter).sort_by do |f|
58
+ f.respond_to?(:weight) ? f.weight : DEFAULT_WEIGHT
59
+ end.reverse!
53
60
  end
54
61
 
55
62
  ##
@@ -59,7 +66,7 @@ module Airbrake
59
66
  # @param [Airbrake::Notice] notice The notice to be filtered
60
67
  # @return [void]
61
68
  def refine(notice)
62
- (@filters + @keys_filters).each do |filter|
69
+ @filters.each do |filter|
63
70
  break if notice.ignored?
64
71
  filter.call(notice)
65
72
  end
@@ -7,6 +7,14 @@ module Airbrake
7
7
  # @return [String]
8
8
  GEM_ROOT_LABEL = '[GEM_ROOT]'.freeze
9
9
 
10
+ ##
11
+ # @return [Integer]
12
+ attr_reader :weight
13
+
14
+ def initialize
15
+ @weight = 120
16
+ end
17
+
10
18
  def call(notice)
11
19
  return unless defined?(Gem)
12
20
 
@@ -26,6 +26,11 @@ module Airbrake
26
26
  class KeysBlacklist
27
27
  include KeysFilter
28
28
 
29
+ def initialize(*)
30
+ super
31
+ @weight = -110
32
+ end
33
+
29
34
  ##
30
35
  # @return [Boolean] true if the key matches at least one pattern, false
31
36
  # otherwise
@@ -18,12 +18,16 @@ module Airbrake
18
18
  # which can compared with payload keys
19
19
  VALID_PATTERN_CLASSES = [String, Symbol, Regexp].freeze
20
20
 
21
+ ##
22
+ # @return [Integer]
23
+ attr_reader :weight
24
+
21
25
  ##
22
26
  # Creates a new KeysBlacklist or KeysWhitelist filter that uses the given
23
27
  # +patterns+ for filtering a notice's payload.
24
28
  #
25
29
  # @param [Array<String,Regexp,Symbol>] patterns
26
- def initialize(logger, *patterns)
30
+ def initialize(logger, patterns)
27
31
  @logger = logger
28
32
  @patterns = patterns
29
33
  @valid_patterns = false
@@ -26,6 +26,11 @@ module Airbrake
26
26
  class KeysWhitelist
27
27
  include KeysFilter
28
28
 
29
+ def initialize(*)
30
+ super
31
+ @weight = -100
32
+ end
33
+
29
34
  ##
30
35
  # @return [Boolean] true if the key doesn't match any pattern, false
31
36
  # otherwise.
@@ -7,8 +7,13 @@ module Airbrake
7
7
  # @return [String]
8
8
  PROJECT_ROOT_LABEL = '[PROJECT_ROOT]'.freeze
9
9
 
10
+ ##
11
+ # @return [Integer]
12
+ attr_reader :weight
13
+
10
14
  def initialize(root_directory)
11
15
  @root_directory = root_directory
16
+ @weight = 100
12
17
  end
13
18
 
14
19
  def call(notice)
@@ -7,6 +7,14 @@ module Airbrake
7
7
  # @return [String]
8
8
  SYSTEM_EXIT_TYPE = 'SystemExit'.freeze
9
9
 
10
+ ##
11
+ # @return [Integer]
12
+ attr_reader :weight
13
+
14
+ def initialize
15
+ @weight = 130
16
+ end
17
+
10
18
  def call(notice)
11
19
  return if notice[:errors].none? { |error| error[:type] == SYSTEM_EXIT_TYPE }
12
20
  notice.ignore!
@@ -4,6 +4,14 @@ module Airbrake
4
4
  # Attaches thread & fiber local variables along with general thread
5
5
  # information.
6
6
  class ThreadFilter
7
+ ##
8
+ # @return [Integer]
9
+ attr_reader :weight
10
+
11
+ def initialize
12
+ @weight = 110
13
+ end
14
+
7
15
  def call(notice)
8
16
  th = Thread.current
9
17
  thread_info = {}
@@ -30,12 +38,17 @@ module Airbrake
30
38
 
31
39
  def thread_variables(th)
32
40
  th.thread_variables.map.with_object({}) do |var, h|
33
- h[var] = th.thread_variable_get(var).inspect
41
+ next if (value = th.thread_variable_get(var)).is_a?(IO)
42
+ h[var] = value
34
43
  end
35
44
  end
36
45
 
37
46
  def fiber_variables(th)
38
- th.keys.map.with_object({}) { |key, h| h[key] = th[key].inspect }
47
+ th.keys.map.with_object({}) do |key, h|
48
+ next if key == :__recursive_key__
49
+ next if (value = th[key]).is_a?(IO)
50
+ h[key] = value
51
+ end
39
52
  end
40
53
 
41
54
  def add_thread_info(th, thread_info)
@@ -35,8 +35,6 @@ module Airbrake
35
35
 
36
36
  @filter_chain = FilterChain.new(@config)
37
37
 
38
- add_filters_for_config_keys
39
-
40
38
  @async_sender = AsyncSender.new(@config)
41
39
  @sync_sender = SyncSender.new(@config)
42
40
  end
@@ -147,16 +145,6 @@ module Airbrake
147
145
  return caller_copy if clean_bt.empty?
148
146
  clean_bt
149
147
  end
150
-
151
- def add_filters_for_config_keys
152
- if @config.blacklist_keys.any?
153
- add_filter(Filters::KeysBlacklist.new(@config.logger, *@config.blacklist_keys))
154
- end
155
-
156
- return if @config.whitelist_keys.none?
157
-
158
- add_filter(Filters::KeysWhitelist.new(@config.logger, *@config.whitelist_keys))
159
- end
160
148
  end
161
149
 
162
150
  ##
@@ -4,5 +4,5 @@
4
4
  module Airbrake
5
5
  ##
6
6
  # @return [String] the library version
7
- AIRBRAKE_RUBY_VERSION = '2.2.0'.freeze
7
+ AIRBRAKE_RUBY_VERSION = '2.2.1'.freeze
8
8
  end
@@ -13,37 +13,10 @@ RSpec.describe Airbrake::FilterChain do
13
13
  Airbrake::Notice.new(config, AirbrakeTestError.new)
14
14
  end
15
15
 
16
- it "executes filters starting from the oldest" do
17
- nums = []
18
-
19
- 3.times do |i|
20
- @chain.add_filter(proc { nums << i })
21
- end
22
-
23
- @chain.refine(notice)
24
-
25
- expect(nums).to eq([0, 1, 2])
26
- end
27
-
28
- it "stops execution once a notice was ignored" do
29
- nums = []
30
-
31
- 5.times do |i|
32
- @chain.add_filter(proc do |notice|
33
- nums << i
34
- notice.ignore! if i == 2
35
- end)
36
- end
37
-
38
- @chain.refine(notice)
39
-
40
- expect(nums).to eq([0, 1, 2])
41
- end
42
-
43
16
  it "executes keys filters last" do
44
17
  notice[:params] = { bingo: 'bango' }
45
- blacklist = Airbrake::Filters::KeysBlacklist.new(config.logger, :bingo)
46
- @chain.add_filter(blacklist)
18
+ config.blacklist_keys = [:bingo]
19
+ @chain = described_class.new(config)
47
20
 
48
21
  @chain.add_filter(
49
22
  proc do |notice|
@@ -55,20 +28,45 @@ RSpec.describe Airbrake::FilterChain do
55
28
  expect(notice[:params][:bingo]).to eq('[Filtered]')
56
29
  end
57
30
 
58
- it "executes library filters before user ones" do
59
- nums = []
31
+ describe "filter weight" do
32
+ let(:filter) do
33
+ Class.new do
34
+ attr_reader :weight
60
35
 
61
- @chain.add_filter(proc { nums << 2 })
36
+ def initialize(weight)
37
+ @weight = weight
38
+ end
62
39
 
63
- priority_filter = proc { nums << 1 }
64
- def priority_filter.to_s
65
- '#<Airbrake::'
40
+ def call(notice)
41
+ notice[:params][:bingo] << @weight
42
+ end
43
+ end
66
44
  end
67
- @chain.add_filter(priority_filter)
68
45
 
69
- @chain.refine(notice)
46
+ it "executes filters from heaviest to lightest" do
47
+ notice[:params][:bingo] = []
48
+
49
+ (0...3).reverse_each do |i|
50
+ @chain.add_filter(filter.new(i))
51
+ end
52
+ @chain.refine(notice)
53
+
54
+ expect(notice[:params][:bingo]).to eq([2, 1, 0])
55
+ end
56
+
57
+ it "stops execution once a notice was ignored" do
58
+ f2 = filter.new(2)
59
+ expect(f2).to receive(:call)
60
+
61
+ f1 = proc { |notice| notice.ignore! }
70
62
 
71
- expect(nums).to eq([1, 2])
63
+ f0 = filter.new(-1)
64
+ expect(f0).not_to receive(:call)
65
+
66
+ [f2, f1, f0].each { |f| @chain.add_filter(f) }
67
+
68
+ @chain.refine(notice)
69
+ end
72
70
  end
73
71
  end
74
72
 
@@ -11,7 +11,7 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
11
11
  subject.call(notice)
12
12
  th.thread_variable_set(:bingo, nil)
13
13
 
14
- expect(notice[:params][:thread][:thread_variables][:bingo]).to eq(':bango')
14
+ expect(notice[:params][:thread][:thread_variables][:bingo]).to eq(:bango)
15
15
  end
16
16
 
17
17
  it "appends fiber variables" do
@@ -19,7 +19,7 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
19
19
  subject.call(notice)
20
20
  th[:bingo] = nil
21
21
 
22
- expect(notice[:params][:thread][:fiber_variables][:bingo]).to eq(':bango')
22
+ expect(notice[:params][:thread][:fiber_variables][:bingo]).to eq(:bango)
23
23
  end
24
24
 
25
25
  it "appends name", skip: !Thread.current.respond_to?(:name) do
@@ -49,4 +49,32 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
49
49
  subject.call(notice)
50
50
  expect(notice[:params][:thread][:safe_level]).to eq(0)
51
51
  end
52
+
53
+ context "when an IO-like object is stored" do
54
+ let(:io_obj) do
55
+ Class.new(IO) do
56
+ def initialize; end
57
+ end.new
58
+ end
59
+
60
+ before do
61
+ expect(io_obj).to be_is_a(IO)
62
+ end
63
+
64
+ it "doesn't append the IO object to thread variables" do
65
+ th.thread_variable_set(:io, io_obj)
66
+ subject.call(notice)
67
+ th.thread_variable_set(:io, nil)
68
+
69
+ expect(notice[:params][:thread][:thread_variables][:io]).to be_nil
70
+ end
71
+
72
+ it "doesn't append the IO object to thread variables" do
73
+ th[:io] = io_obj
74
+ subject.call(notice)
75
+ th[:io] = nil
76
+
77
+ expect(notice[:params][:thread][:fiber_variables][:io]).to be_nil
78
+ end
79
+ end
52
80
  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: 2.2.0
4
+ version: 2.2.1
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: 2017-05-01 00:00:00.000000000 Z
11
+ date: 2017-05-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -168,7 +168,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
168
168
  version: '0'
169
169
  requirements: []
170
170
  rubyforge_project:
171
- rubygems_version: 2.6.8
171
+ rubygems_version: 2.2.5
172
172
  signing_key:
173
173
  specification_version: 4
174
174
  summary: Ruby notifier for https://airbrake.io