airbrake-ruby 2.2.0 → 2.2.1

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
  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