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 +4 -4
- data/lib/airbrake-ruby/filter_chain.rb +32 -25
- data/lib/airbrake-ruby/filters/gem_root_filter.rb +8 -0
- data/lib/airbrake-ruby/filters/keys_blacklist.rb +5 -0
- data/lib/airbrake-ruby/filters/keys_filter.rb +5 -1
- data/lib/airbrake-ruby/filters/keys_whitelist.rb +5 -0
- data/lib/airbrake-ruby/filters/root_directory_filter.rb +5 -0
- data/lib/airbrake-ruby/filters/system_exit_filter.rb +8 -0
- data/lib/airbrake-ruby/filters/thread_filter.rb +15 -2
- data/lib/airbrake-ruby/notifier.rb +0 -12
- data/lib/airbrake-ruby/version.rb +1 -1
- data/spec/filter_chain_spec.rb +36 -38
- data/spec/filters/thread_filter_spec.rb +30 -2
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 21223403ddfa03e2f851d2cb5c4a74130e17840f
|
4
|
+
data.tar.gz: ab65e845c6053434813b8bbf0f23edaa80dad44d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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 [
|
12
|
-
|
13
|
-
|
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
|
-
#
|
17
|
-
|
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
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
37
|
-
|
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
|
-
|
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
|
-
|
49
|
-
|
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
|
-
|
69
|
+
@filters.each do |filter|
|
63
70
|
break if notice.ignored?
|
64
71
|
filter.call(notice)
|
65
72
|
end
|
@@ -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,
|
30
|
+
def initialize(logger, patterns)
|
27
31
|
@logger = logger
|
28
32
|
@patterns = patterns
|
29
33
|
@valid_patterns = false
|
@@ -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
|
-
|
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({})
|
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
|
##
|
data/spec/filter_chain_spec.rb
CHANGED
@@ -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
|
-
|
46
|
-
@chain.
|
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
|
-
|
59
|
-
|
31
|
+
describe "filter weight" do
|
32
|
+
let(:filter) do
|
33
|
+
Class.new do
|
34
|
+
attr_reader :weight
|
60
35
|
|
61
|
-
|
36
|
+
def initialize(weight)
|
37
|
+
@weight = weight
|
38
|
+
end
|
62
39
|
|
63
|
-
|
64
|
-
|
65
|
-
|
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
|
-
|
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
|
-
|
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(
|
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(
|
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.
|
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-
|
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.
|
171
|
+
rubygems_version: 2.2.5
|
172
172
|
signing_key:
|
173
173
|
specification_version: 4
|
174
174
|
summary: Ruby notifier for https://airbrake.io
|