airbrake-ruby 2.0.0 → 2.1.0

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: abc8e8ee3aac5103d60b365927bb65426a3118d4
4
- data.tar.gz: 3b6721865f222b5dc2fd26c4456de385a0761ddf
3
+ metadata.gz: d83d667d85784f12930d891e4a40f33ff5021d32
4
+ data.tar.gz: 27abbb08a24e1f5037134d779e1cd00bb6b2c6b9
5
5
  SHA512:
6
- metadata.gz: 54a86bed42a190518bf82281abb3354fc74b951ffde54cc9b83c796c0d0cd8c8960bac7e1a635b614c6eebc8b985495646006c0ccfde4ed0f2df2221ba2c31c9
7
- data.tar.gz: 20e077993ec39e48f2d548b5978f4815a181bd1ca51e23b88054d1f4d249dabfc5cb0247d9b9a5efb3800b2a6397d91b33865e0379548ae745d18356a56eab09
6
+ metadata.gz: 97bde22452bbf79d34d127de8972799f482ee9476a02760de6f9089d02e548a75fa73657f02dd1a93e99ee3ae27b85f176b00d9c362b3d78c837dc49ae2ab6d6
7
+ data.tar.gz: 9aa4f9c47307cf45339ebabfad298e1217498318029a5423e47a2f4f91d63b14022a41f39940bccd1b67de4f5f54fae8a2dc4dd00b97912ad2c454bfcc60d63e
@@ -20,6 +20,10 @@ require 'airbrake-ruby/filters'
20
20
  require 'airbrake-ruby/filters/keys_filter'
21
21
  require 'airbrake-ruby/filters/keys_whitelist'
22
22
  require 'airbrake-ruby/filters/keys_blacklist'
23
+ require 'airbrake-ruby/filters/gem_root_filter'
24
+ require 'airbrake-ruby/filters/system_exit_filter'
25
+ require 'airbrake-ruby/filters/root_directory_filter'
26
+ require 'airbrake-ruby/filters/thread_filter'
23
27
  require 'airbrake-ruby/filter_chain'
24
28
  require 'airbrake-ruby/notifier'
25
29
 
@@ -71,10 +75,16 @@ module Airbrake
71
75
  # for special cases where we need to work around older implementations
72
76
  RUBY_20 = RUBY_VERSION.start_with?('2.0')
73
77
 
78
+ ##
79
+ # @return [Boolean] true if current Ruby is JRuby. The result is used for
80
+ # special cases where we need to work around older implementations
81
+ JRUBY = (RUBY_ENGINE == 'jruby')
82
+
74
83
  ##
75
84
  # A Hash that holds all notifiers. The keys of the Hash are notifier
76
- # names, the values are Airbrake::Notifier instances.
77
- @notifiers = {}
85
+ # names, the values are Airbrake::Notifier instances. If a notifier is not
86
+ # assigned to the hash, then it returns a null object (NilNotifier).
87
+ @notifiers = Hash.new(NilNotifier.new)
78
88
 
79
89
  class << self
80
90
  ##
@@ -107,7 +117,7 @@ module Airbrake
107
117
  # c.project_key = '91ac5e4a37496026c6837f63276ed2b6'
108
118
  # end
109
119
  #
110
- # @param [Symbol] notifier the name to be associated with the notifier
120
+ # @param [Symbol] notifier_name the name to be associated with the notifier
111
121
  # @yield [config] The configuration object
112
122
  # @yieldparam config [Airbrake::Config]
113
123
  # @return [void]
@@ -146,7 +156,7 @@ module Airbrake
146
156
  # @return [Airbrake::Promise]
147
157
  # @see .notify_sync
148
158
  def notify(exception, params = {})
149
- @notifiers[:default] && @notifiers[:default].notify(exception, params)
159
+ @notifiers[:default].notify(exception, params)
150
160
  end
151
161
 
152
162
  ##
@@ -159,7 +169,7 @@ module Airbrake
159
169
  # @return [Hash{String=>String}] the reponse from the server
160
170
  # @see .notify
161
171
  def notify_sync(exception, params = {})
162
- @notifiers[:default] && @notifiers[:default].notify_sync(exception, params)
172
+ @notifiers[:default].notify_sync(exception, params)
163
173
  end
164
174
 
165
175
  ##
@@ -189,7 +199,7 @@ module Airbrake
189
199
  # @return [void]
190
200
  # @note Once a filter was added, there's no way to delete it
191
201
  def add_filter(filter = nil, &block)
192
- @notifiers[:default] && @notifiers[:default].add_filter(filter, &block)
202
+ @notifiers[:default].add_filter(filter, &block)
193
203
  end
194
204
 
195
205
  ##
@@ -208,7 +218,7 @@ module Airbrake
208
218
  # @return [Airbrake::Notice] the notice built with help of the given
209
219
  # arguments
210
220
  def build_notice(exception, params = {})
211
- @notifiers[:default] && @notifiers[:default].build_notice(exception, params)
221
+ @notifiers[:default].build_notice(exception, params)
212
222
  end
213
223
 
214
224
  ##
@@ -222,7 +232,7 @@ module Airbrake
222
232
  #
223
233
  # @return [void]
224
234
  def close
225
- @notifiers[:default] && @notifiers[:default].close
235
+ @notifiers[:default].close
226
236
  end
227
237
 
228
238
  ##
@@ -237,7 +247,7 @@ module Airbrake
237
247
  # @option deploy_params [Symbol] :version
238
248
  # @return [void]
239
249
  def create_deploy(deploy_params)
240
- @notifiers[:default] && @notifiers[:default].create_deploy(deploy_params)
250
+ @notifiers[:default].create_deploy(deploy_params)
241
251
  end
242
252
  end
243
253
  end
@@ -8,22 +8,9 @@ module Airbrake
8
8
  # @since v1.0.0
9
9
  class FilterChain
10
10
  ##
11
- # Replaces paths to gems with a placeholder.
12
- # @return [Proc]
13
- GEM_ROOT_FILTER = proc do |notice|
14
- return unless defined?(Gem)
15
-
16
- notice[:errors].each do |error|
17
- Gem.path.each do |gem_path|
18
- error[:backtrace].each do |frame|
19
- # If the frame is unparseable, then 'file' is nil, thus nothing to
20
- # filter (all frame's data is in 'function' instead).
21
- next unless (file = frame[:file])
22
- file.sub!(/\A#{gem_path}/, '[GEM_ROOT]'.freeze)
23
- end
24
- end
25
- end
26
- end
11
+ # @return [String] the namespace for filters, which are executed first,
12
+ # before any other filters
13
+ LIB_NAMESPACE = '#<Airbrake::'.freeze
27
14
 
28
15
  ##
29
16
  # Filters to be executed last. By this time all permutations on a notice
@@ -34,35 +21,35 @@ module Airbrake
34
21
  Airbrake::Filters::KeysWhitelist
35
22
  ].freeze
36
23
 
37
- ##
38
- # Skip over SystemExit exceptions, because they're just noise.
39
- # @return [Proc]
40
- SYSTEM_EXIT_FILTER = proc do |notice|
41
- if notice[:errors].any? { |error| error[:type] == 'SystemExit' }
42
- notice.ignore!
43
- end
44
- end
45
-
46
24
  ##
47
25
  # @param [Airbrake::Config] config
48
26
  def initialize(config)
49
27
  @filters = []
50
28
  @keys_filters = []
51
29
 
52
- [SYSTEM_EXIT_FILTER, GEM_ROOT_FILTER].each do |filter|
53
- add_filter(filter)
30
+ [Airbrake::Filters::SystemExitFilter,
31
+ Airbrake::Filters::GemRootFilter,
32
+ Airbrake::Filters::ThreadFilter].each do |filter|
33
+ @filters << filter.new
54
34
  end
55
35
 
56
36
  root_directory = config.root_directory
57
- add_filter(root_directory_filter(root_directory)) if root_directory
37
+ return unless root_directory
38
+
39
+ @filters << Airbrake::Filters::RootDirectoryFilter.new(root_directory)
58
40
  end
59
41
 
60
42
  ##
61
43
  # Adds a filter to the filter chain.
44
+ #
62
45
  # @param [#call] filter The filter object (proc, class, module, etc)
46
+ # @return [void]
63
47
  def add_filter(filter)
64
48
  return @keys_filters << filter if KEYS_FILTERS.include?(filter.class)
65
- @filters << filter
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
66
53
  end
67
54
 
68
55
  ##
@@ -77,18 +64,5 @@ module Airbrake
77
64
  filter.call(notice)
78
65
  end
79
66
  end
80
-
81
- private
82
-
83
- def root_directory_filter(root_directory)
84
- proc do |notice|
85
- notice[:errors].each do |error|
86
- error[:backtrace].each do |frame|
87
- next unless (file = frame[:file])
88
- file.sub!(/\A#{root_directory}/, '[PROJECT_ROOT]'.freeze)
89
- end
90
- end
91
- end
92
- end
93
67
  end
94
68
  end
@@ -5,6 +5,6 @@ module Airbrake
5
5
  ##
6
6
  # @return [Array<Symbol>] parts of a Notice's payload that can be modified
7
7
  # by various filters
8
- FILTERABLE_KEYS = [:environment, :session, :params].freeze
8
+ FILTERABLE_KEYS = %i[environment session params].freeze
9
9
  end
10
10
  end
@@ -0,0 +1,26 @@
1
+ module Airbrake
2
+ module Filters
3
+ ##
4
+ # Replaces paths to gems with a placeholder.
5
+ class GemRootFilter
6
+ ##
7
+ # @return [String]
8
+ GEM_ROOT_LABEL = '[GEM_ROOT]'.freeze
9
+
10
+ def call(notice)
11
+ return unless defined?(Gem)
12
+
13
+ notice[:errors].each do |error|
14
+ Gem.path.each do |gem_path|
15
+ error[:backtrace].each do |frame|
16
+ # If the frame is unparseable, then 'file' is nil, thus nothing to
17
+ # filter (all frame's data is in 'function' instead).
18
+ next unless (file = frame[:file])
19
+ file.sub!(/\A#{gem_path}/, GEM_ROOT_LABEL)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,24 @@
1
+ module Airbrake
2
+ module Filters
3
+ ##
4
+ # Replaces root directory with a label.
5
+ class RootDirectoryFilter
6
+ ##
7
+ # @return [String]
8
+ PROJECT_ROOT_LABEL = '[PROJECT_ROOT]'.freeze
9
+
10
+ def initialize(root_directory)
11
+ @root_directory = root_directory
12
+ end
13
+
14
+ def call(notice)
15
+ notice[:errors].each do |error|
16
+ error[:backtrace].each do |frame|
17
+ next unless (file = frame[:file])
18
+ file.sub!(/\A#{@root_directory}/, PROJECT_ROOT_LABEL)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,16 @@
1
+ module Airbrake
2
+ module Filters
3
+ ##
4
+ # Skip over SystemExit exceptions, because they're just noise.
5
+ class SystemExitFilter
6
+ ##
7
+ # @return [String]
8
+ SYSTEM_EXIT_TYPE = 'SystemExit'.freeze
9
+
10
+ def call(notice)
11
+ return if notice[:errors].none? { |error| error[:type] == SYSTEM_EXIT_TYPE }
12
+ notice.ignore!
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,50 @@
1
+ module Airbrake
2
+ module Filters
3
+ ##
4
+ # Attaches thread & fiber local variables along with general thread
5
+ # information.
6
+ class ThreadFilter
7
+ def call(notice)
8
+ th = Thread.current
9
+ thread_info = {}
10
+
11
+ if (vars = thread_variables(th)).any?
12
+ thread_info[:thread_variables] = vars
13
+ end
14
+
15
+ if (vars = fiber_variables(th)).any?
16
+ thread_info[:fiber_variables] = vars
17
+ end
18
+
19
+ # Present in Ruby 2.3+.
20
+ if th.respond_to?(:name) && (name = th.name)
21
+ thread_info[:name] = name
22
+ end
23
+
24
+ add_thread_info(th, thread_info)
25
+
26
+ notice[:params][:thread] = thread_info
27
+ end
28
+
29
+ private
30
+
31
+ def thread_variables(th)
32
+ th.thread_variables.map.with_object({}) do |var, h|
33
+ h[var] = th.thread_variable_get(var).inspect
34
+ end
35
+ end
36
+
37
+ def fiber_variables(th)
38
+ th.keys.map.with_object({}) { |key, h| h[key] = th[key].inspect }
39
+ end
40
+
41
+ def add_thread_info(th, thread_info)
42
+ thread_info[:self] = th.inspect
43
+ thread_info[:group] = th.group.list.map(&:inspect)
44
+ thread_info[:priority] = th.priority
45
+
46
+ thread_info[:safe_level] = th.safe_level unless Airbrake::JRUBY
47
+ end
48
+ end
49
+ end
50
+ end
@@ -44,12 +44,12 @@ module Airbrake
44
44
 
45
45
  # @return [Array<Symbol>] the list of keys that can be be overwritten with
46
46
  # {Airbrake::Notice#[]=}
47
- WRITABLE_KEYS = [
48
- :notifier,
49
- :context,
50
- :environment,
51
- :session,
52
- :params
47
+ WRITABLE_KEYS = %i[
48
+ notifier
49
+ context
50
+ environment
51
+ session
52
+ params
53
53
  ].freeze
54
54
 
55
55
  ##
@@ -89,12 +89,9 @@ module Airbrake
89
89
  # @macro see_public_api_method
90
90
  def create_deploy(deploy_params)
91
91
  deploy_params[:environment] ||= @config.environment
92
-
93
- host = @config.endpoint.to_s.split(@config.endpoint.path).first
94
- path = "/api/v4/projects/#{@config.project_id}/deploys?key=#{@config.project_key}"
95
-
92
+ path = "api/v4/projects/#{@config.project_id}/deploys?key=#{@config.project_key}"
96
93
  promise = Airbrake::Promise.new
97
- @sync_sender.send(deploy_params, promise, URI.join(host, path))
94
+ @sync_sender.send(deploy_params, promise, URI.join(@config.host, path))
98
95
  promise
99
96
  end
100
97
 
@@ -159,4 +156,23 @@ module Airbrake
159
156
  add_filter(Filters::KeysWhitelist.new(@config.logger, *@config.whitelist_keys))
160
157
  end
161
158
  end
159
+
160
+ ##
161
+ # NilNotifier is a no-op notifier, which mimics +Airbrake::Notifier+ and
162
+ # serves only for the purpose of making the library API easier to use.
163
+ #
164
+ # @since 2.1.0
165
+ class NilNotifier
166
+ def notify(_exception, _params = {}); end
167
+
168
+ def notify_sync(_exception, _params); end
169
+
170
+ def add_filter(_filter = nil, &_block); end
171
+
172
+ def build_notice(_exception, _params); end
173
+
174
+ def close; end
175
+
176
+ def create_deploy(_deploy_params); end
177
+ end
162
178
  end
@@ -4,5 +4,5 @@
4
4
  module Airbrake
5
5
  ##
6
6
  # @return [String] the library version
7
- AIRBRAKE_RUBY_VERSION = '2.0.0'.freeze
7
+ AIRBRAKE_RUBY_VERSION = '2.1.0'.freeze
8
8
  end
@@ -17,12 +17,18 @@ RSpec.describe Airbrake do
17
17
  end
18
18
 
19
19
  after do
20
- described_class.instance_variable_set(:@notifiers, {})
20
+ described_class.instance_variable_set(
21
+ :@notifiers,
22
+ Hash.new(Airbrake::NilNotifier.new)
23
+ )
21
24
  end
22
25
 
23
26
  shared_examples 'non-configured notifier handling' do |method|
24
27
  it "returns nil if there is no configured notifier when using #{method}" do
25
- described_class.instance_variable_set(:@notifiers, {})
28
+ described_class.instance_variable_set(
29
+ :@notifiers,
30
+ Hash.new(Airbrake::NilNotifier.new)
31
+ )
26
32
  expect(described_class.__send__(method, 'bingo')).to be_nil
27
33
  end
28
34
  end
@@ -94,7 +100,7 @@ RSpec.describe Airbrake do
94
100
  notifiers = described_class.instance_variable_get(:@notifiers)
95
101
 
96
102
  expect(notifiers).to be_a(Hash)
97
- expect(notifiers.keys).to eq([:default, :bingo])
103
+ expect(notifiers.keys).to eq(%i[default bingo])
98
104
  expect(notifiers.values).to all(satisfy { |v| v.is_a?(Airbrake::Notifier) })
99
105
  end
100
106
 
@@ -122,11 +128,11 @@ RSpec.describe Airbrake do
122
128
  filter_chain = notifier.instance_variable_get(:@filter_chain)
123
129
  filters = filter_chain.instance_variable_get(:@filters)
124
130
 
125
- expect(filters.size).to eq(3)
131
+ expect(filters.size).to eq(4)
126
132
 
127
133
  described_class.add_filter {}
128
134
 
129
- expect(filters.size).to eq(4)
135
+ expect(filters.size).to eq(5)
130
136
  expect(filters.last).to be_a(Proc)
131
137
  end
132
138
  end
@@ -12,9 +12,9 @@ RSpec.describe Airbrake::Config::Validator do
12
12
  end
13
13
 
14
14
  it "sets correct error message" do
15
- expect { subject.valid_project_id? }.
16
- to change { subject.error_message }.
17
- to(/:project_id is required/)
15
+ expect { subject.valid_project_id? }.to(
16
+ change { subject.error_message }.to(/:project_id is required/)
17
+ )
18
18
  end
19
19
  end
20
20
 
@@ -28,8 +28,9 @@ RSpec.describe Airbrake::Config::Validator do
28
28
 
29
29
  it "sets correct error message" do
30
30
  expect { subject.valid_project_id? }.
31
- to change { subject.error_message }.
32
- to(/:project_id is required/)
31
+ to(
32
+ change { subject.error_message }.to(/:project_id is required/)
33
+ )
33
34
  end
34
35
  end
35
36
 
@@ -41,9 +42,9 @@ RSpec.describe Airbrake::Config::Validator do
41
42
  end
42
43
 
43
44
  it "sets correct error message" do
44
- expect { subject.valid_project_id? }.
45
- to change { subject.error_message }.
46
- to(/:project_id is required/)
45
+ expect { subject.valid_project_id? }.to(
46
+ change { subject.error_message }.to(/:project_id is required/)
47
+ )
47
48
  end
48
49
  end
49
50
 
@@ -55,7 +56,7 @@ RSpec.describe Airbrake::Config::Validator do
55
56
  end
56
57
 
57
58
  it "doesn't set the error message" do
58
- expect { subject.valid_project_id? }.not_to change { subject.error_message }
59
+ expect { subject.valid_project_id? }.not_to(change { subject.error_message })
59
60
  end
60
61
  end
61
62
  end
@@ -68,7 +69,7 @@ RSpec.describe Airbrake::Config::Validator do
68
69
  end
69
70
 
70
71
  it "doesn't set the error message" do
71
- expect { subject.valid_project_id? }.not_to change { subject.error_message }
72
+ expect { subject.valid_project_id? }.not_to(change { subject.error_message })
72
73
  end
73
74
  end
74
75
  end
@@ -97,7 +98,7 @@ RSpec.describe Airbrake::Config::Validator do
97
98
  end
98
99
 
99
100
  it "doesn't set the error message" do
100
- expect { subject.valid_project_key? }.not_to change { subject.error_message }
101
+ expect { subject.valid_project_key? }.not_to(change { subject.error_message })
101
102
  end
102
103
  end
103
104
  end
@@ -110,9 +111,9 @@ RSpec.describe Airbrake::Config::Validator do
110
111
  end
111
112
 
112
113
  it "sets correct error message" do
113
- expect { subject.valid_project_key? }.
114
- to change { subject.error_message }.
115
- to(/:project_key is required/)
114
+ expect { subject.valid_project_key? }.to(
115
+ change { subject.error_message }.to(/:project_key is required/)
116
+ )
116
117
  end
117
118
  end
118
119
  end
@@ -126,7 +127,7 @@ RSpec.describe Airbrake::Config::Validator do
126
127
  end
127
128
 
128
129
  it "doesn't set the error message" do
129
- expect { subject.valid_environment? }.not_to change { subject.error_message }
130
+ expect { subject.valid_environment? }.not_to(change { subject.error_message })
130
131
  end
131
132
  end
132
133
 
@@ -139,9 +140,10 @@ RSpec.describe Airbrake::Config::Validator do
139
140
  end
140
141
 
141
142
  it "sets the error message" do
142
- expect { subject.valid_environment? }.
143
- to change { subject.error_message }.
144
- to(/the 'environment' option must be configured with a Symbol/)
143
+ expect { subject.valid_environment? }.to(
144
+ change { subject.error_message }.
145
+ to(/the 'environment' option must be configured with a Symbol/)
146
+ )
145
147
  end
146
148
  end
147
149
 
@@ -153,7 +155,7 @@ RSpec.describe Airbrake::Config::Validator do
153
155
  end
154
156
 
155
157
  it "doesn't set the error message" do
156
- expect { subject.valid_environment? }.not_to change { subject.error_message }
158
+ expect { subject.valid_environment? }.not_to(change { subject.error_message })
157
159
  end
158
160
  end
159
161
 
@@ -165,7 +167,7 @@ RSpec.describe Airbrake::Config::Validator do
165
167
  end
166
168
 
167
169
  it "doesn't set the error message" do
168
- expect { subject.valid_environment? }.not_to change { subject.error_message }
170
+ expect { subject.valid_environment? }.not_to(change { subject.error_message })
169
171
  end
170
172
  end
171
173
 
@@ -181,7 +183,7 @@ RSpec.describe Airbrake::Config::Validator do
181
183
  end
182
184
 
183
185
  it "doesn't set the error message" do
184
- expect { subject.valid_environment? }.not_to change { subject.error_message }
186
+ expect { subject.valid_environment? }.not_to(change { subject.error_message })
185
187
  end
186
188
  end
187
189
  end
@@ -221,7 +221,7 @@ RSpec.describe Airbrake::Config do
221
221
  context "and when 'ignore_environments' contains Strings" do
222
222
  it "returns true" do
223
223
  config.environment = :bango
224
- config.ignore_environments = %w(bango)
224
+ config.ignore_environments = %w[bango]
225
225
 
226
226
  expect(config.ignored_environment?).to be_truthy
227
227
  end
@@ -54,6 +54,22 @@ RSpec.describe Airbrake::FilterChain do
54
54
  @chain.refine(notice)
55
55
  expect(notice[:params][:bingo]).to eq('[Filtered]')
56
56
  end
57
+
58
+ it "executes library filters before user ones" do
59
+ nums = []
60
+
61
+ @chain.add_filter(proc { nums << 2 })
62
+
63
+ priority_filter = proc { nums << 1 }
64
+ def priority_filter.to_s
65
+ '#<Airbrake::'
66
+ end
67
+ @chain.add_filter(priority_filter)
68
+
69
+ @chain.refine(notice)
70
+
71
+ expect(nums).to eq([1, 2])
72
+ end
57
73
  end
58
74
 
59
75
  describe "default backtrace filters" do
@@ -181,7 +197,7 @@ RSpec.describe Airbrake::FilterChain do
181
197
 
182
198
  expect(notice[:errors].first[:file]).to be_nil
183
199
  expect { @chain.refine(notice) }.
184
- not_to change { notice[:errors].first[:file] }
200
+ not_to(change { notice[:errors].first[:file] })
185
201
  end
186
202
  end
187
203
 
@@ -200,7 +216,7 @@ RSpec.describe Airbrake::FilterChain do
200
216
 
201
217
  expect(notice[:errors].first[:file]).to be_nil
202
218
  expect { filter_chain.refine(notice) }.
203
- not_to change { notice[:errors].first[:file] }
219
+ not_to(change { notice[:errors].first[:file] })
204
220
  end
205
221
  end
206
222
  end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Airbrake::Filters::ThreadFilter do
4
+ subject { described_class.new }
5
+
6
+ let(:notice) { Airbrake::Notice.new(Airbrake::Config.new, AirbrakeTestError.new) }
7
+ let(:th) { Thread.current }
8
+
9
+ it "appends thread variables" do
10
+ th.thread_variable_set(:bingo, :bango)
11
+ subject.call(notice)
12
+ th.thread_variable_set(:bingo, nil)
13
+
14
+ expect(notice[:params][:thread][:thread_variables][:bingo]).to eq(':bango')
15
+ end
16
+
17
+ it "appends fiber variables" do
18
+ th[:bingo] = :bango
19
+ subject.call(notice)
20
+ th[:bingo] = nil
21
+
22
+ expect(notice[:params][:thread][:fiber_variables][:bingo]).to eq(':bango')
23
+ end
24
+
25
+ it "appends name", skip: !Thread.current.respond_to?(:name) do
26
+ th.name = 'bingo'
27
+ subject.call(notice)
28
+ th.name = nil
29
+
30
+ expect(notice[:params][:thread][:name]).to eq('bingo')
31
+ end
32
+
33
+ it "appends thread inspect (self)" do
34
+ subject.call(notice)
35
+ expect(notice[:params][:thread][:self]).to match(/\A#<Thread:.+ run>\z/)
36
+ end
37
+
38
+ it "appends thread group" do
39
+ subject.call(notice)
40
+ expect(notice[:params][:thread][:group][0]).to match(/\A#<Thread:.+ run>\z/)
41
+ end
42
+
43
+ it "appends priority" do
44
+ subject.call(notice)
45
+ expect(notice[:params][:thread][:priority]).to eq(0)
46
+ end
47
+
48
+ it "appends safe_level", skip: Airbrake::JRUBY do
49
+ subject.call(notice)
50
+ expect(notice[:params][:thread][:safe_level]).to eq(0)
51
+ end
52
+ end
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+
2
3
  require 'spec_helper'
3
4
 
4
5
  RSpec.describe Airbrake::Notifier do
@@ -153,9 +154,13 @@ RSpec.describe Airbrake::Notifier do
153
154
 
154
155
  it "features 'params'" do
155
156
  expect_a_request_with_body(
156
- /"params":{"bingo":\["bango"\],"bongo":"bish"}/
157
+ /"params":{"bingo":\["bango"\],"bongo":"bish".*}/
157
158
  )
158
159
  end
160
+
161
+ it "features 'params/thread'" do
162
+ expect_a_request_with_body(/"params":{.*"thread":{.*}/)
163
+ end
159
164
  end
160
165
  end
161
166
 
@@ -359,7 +364,7 @@ RSpec.describe Airbrake::Notifier do
359
364
  include_examples(
360
365
  'truncation',
361
366
  params,
362
- /"params":{"bingo":{"bango":{"bongo":".+ObjectWithIoIvars.+"}}}/
367
+ /"params":{"bingo":{"bango":{"bongo":".+ObjectWithIoIvars.+"}}.*}/
363
368
  )
364
369
  end
365
370
 
@@ -368,7 +373,7 @@ RSpec.describe Airbrake::Notifier do
368
373
  include_examples(
369
374
  'truncation',
370
375
  params,
371
- /"params":{"bingo":\[\[".+ObjectWithIoIvars.+"\]\]}/
376
+ /"params":{"bingo":\[\[".+ObjectWithIoIvars.+"\]\].*}/
372
377
  )
373
378
  end
374
379
  end
@@ -381,7 +386,7 @@ RSpec.describe Airbrake::Notifier do
381
386
 
382
387
  sleep 1
383
388
 
384
- expect_a_request_with_body(/params":{"bingo":"bango"}/)
389
+ expect_a_request_with_body(/params":{"bingo":"bango".*}/)
385
390
  end
386
391
 
387
392
  it "returns a promise" do
@@ -405,7 +410,7 @@ RSpec.describe Airbrake::Notifier do
405
410
  notifier.close
406
411
  end
407
412
 
408
- it "respawns workers on fork()", skip: %w(jruby rbx).include?(RUBY_ENGINE) do
413
+ it "respawns workers on fork()", skip: %w[jruby rbx].include?(RUBY_ENGINE) do
409
414
  out = StringIO.new
410
415
  notifier = described_class.new(airbrake_params.merge(logger: Logger.new(out)))
411
416
 
@@ -440,12 +445,12 @@ RSpec.describe Airbrake::Notifier do
440
445
 
441
446
  expect(
442
447
  a_request(:post, endpoint).
443
- with(body: /params":{"password":"\[Filtered\]"}/)
448
+ with(body: /params":{"password":"\[Filtered\]".*}/)
444
449
  ).to have_been_made.once
445
450
  end
446
451
 
447
452
  it "accepts multiple filters" do
448
- [:bingo, :bongo, :bash].each do |key|
453
+ %i[bingo bongo bash].each do |key|
449
454
  @airbrake.add_filter do |notice|
450
455
  notice[:params][key] = '[Filtered]'.freeze if notice[:params][key]
451
456
  end
@@ -454,7 +459,7 @@ RSpec.describe Airbrake::Notifier do
454
459
  @airbrake.notify_sync(ex, bingo: ['bango'], bongo: 'bish', bash: 'bosh')
455
460
 
456
461
  # rubocop:disable Metrics/LineLength
457
- body = /"params":{"bingo":"\[Filtered\]","bongo":"\[Filtered\]","bash":"\[Filtered\]"}/
462
+ body = /"params":{"bingo":"\[Filtered\]","bongo":"\[Filtered\]","bash":"\[Filtered\]".*}/
458
463
  # rubocop:enable Metrics/LineLength
459
464
 
460
465
  expect(
@@ -538,10 +543,27 @@ RSpec.describe Airbrake::Notifier do
538
543
  "https://airbrake.io/api/v4/projects/#{project_id}/deploys?key=#{project_key}"
539
544
  end
540
545
 
541
- it "sends a request to the deploy API" do
546
+ before do
542
547
  stub_request(:post, deploy_endpoint).to_return(status: 201, body: '{"id":"123"}')
548
+ end
549
+
550
+ it "sends a request to the deploy API" do
543
551
  @airbrake.create_deploy({})
544
552
  expect(a_request(:post, deploy_endpoint)).to have_been_made.once
545
553
  end
554
+
555
+ context "when a host contains paths" do
556
+ let(:deploy_host) { "https://example.net/errbit/" }
557
+
558
+ let(:deploy_endpoint) do
559
+ "#{deploy_host}api/v4/projects/#{project_id}/deploys?key=#{project_key}"
560
+ end
561
+
562
+ it "sends a request to the deploy API" do
563
+ airbrake = described_class.new(airbrake_params.merge(host: deploy_host))
564
+ airbrake.create_deploy({})
565
+ expect(a_request(:post, deploy_endpoint)).to have_been_made.once
566
+ end
567
+ end
546
568
  end
547
569
  end
@@ -49,28 +49,28 @@ RSpec.describe "Airbrake::Notifier blacklist_keys" do
49
49
  end
50
50
 
51
51
  context "when blacklisting with a Regexp" do
52
- let(:expected_body) { /"params":{"bingo":"\[Filtered\]"}/ }
52
+ let(:expected_body) { /"params":{"bingo":"\[Filtered\]".*}/ }
53
53
  include_examples('blacklisting', [/\Abin/], bingo: 'bango')
54
54
  end
55
55
 
56
56
  context "when blacklisting with a Symbol" do
57
- let(:expected_body) { /"params":{"bingo":"\[Filtered\]"}/ }
57
+ let(:expected_body) { /"params":{"bingo":"\[Filtered\]".*}/ }
58
58
  include_examples('blacklisting', [:bingo], bingo: 'bango')
59
59
  end
60
60
 
61
61
  context "when blacklisting with a String" do
62
- let(:expected_body) { /"params":{"bingo":"\[Filtered\]"}/ }
62
+ let(:expected_body) { /"params":{"bingo":"\[Filtered\]".*}/ }
63
63
  include_examples('blacklisting', ['bingo'], bingo: 'bango')
64
64
  end
65
65
 
66
66
  context "when payload has a hash" do
67
67
  context "and it is a non-recursive hash" do
68
- let(:expected_body) { /"params":{"bongo":{"bish":"\[Filtered\]"}}/ }
68
+ let(:expected_body) { /"params":{"bongo":{"bish":"\[Filtered\]"}.*}/ }
69
69
  include_examples('blacklisting', ['bish'], bongo: { bish: 'bash' })
70
70
  end
71
71
 
72
72
  context "and it is a recursive hash" do
73
- let(:expected_body) { /"params":{"bingo":{"bango":"\[Filtered\]"}}/ }
73
+ let(:expected_body) { /"params":{"bingo":{"bango":"\[Filtered\]"}.*}/ }
74
74
 
75
75
  bongo = { bingo: {} }
76
76
  bongo[:bingo][:bango] = bongo
@@ -88,13 +88,13 @@ RSpec.describe "Airbrake::Notifier blacklist_keys" do
88
88
  end
89
89
 
90
90
  context "when there was a proc provided, which returns an array of keys" do
91
- let(:expected_body) { /"params":{"bingo":"\[Filtered\]","bongo":"bish"}/ }
91
+ let(:expected_body) { /"params":{"bingo":"\[Filtered\]","bongo":"bish".*}/ }
92
92
  include_examples('blacklisting', [proc { 'bingo' }], bingo: 'bango', bongo: 'bish')
93
93
  end
94
94
 
95
95
  context "when there was a proc provided along with normal keys" do
96
96
  let(:expected_body) do
97
- /"params":{"bingo":"bango","bongo":"\[Filtered\]","bash":"\[Filtered\]"}/
97
+ /"params":{"bingo":"bango","bongo":"\[Filtered\]","bash":"\[Filtered\]".*}/
98
98
  end
99
99
 
100
100
  include_examples(
@@ -117,7 +117,7 @@ RSpec.describe "Airbrake::Notifier blacklist_keys" do
117
117
 
118
118
  notifier.notify_sync(ex, bingo: 'bango', bongo: 'bish')
119
119
 
120
- expect_a_request_with_body(/"params":{"bingo":"bango","bongo":"bish"}/)
120
+ expect_a_request_with_body(/"params":{"bingo":"bango","bongo":"bish".*}/)
121
121
  end
122
122
  end
123
123
 
@@ -139,7 +139,7 @@ RSpec.describe "Airbrake::Notifier blacklist_keys" do
139
139
  notifier.notify_sync(ex, bingo: 'bango', bongo: 'bish')
140
140
 
141
141
  expect_a_request_with_body(
142
- /"params":{"bingo":"\[Filtered\]","bongo":"bish"}/
142
+ /"params":{"bingo":"\[Filtered\]","bongo":"bish".*}/
143
143
  )
144
144
  end
145
145
  end
@@ -201,7 +201,7 @@ RSpec.describe Airbrake::Notifier do
201
201
  context "when the current env and notify envs are the same" do
202
202
  params = {
203
203
  environment: :development,
204
- ignore_environments: [:production, :development]
204
+ ignore_environments: %i[production development]
205
205
  }
206
206
 
207
207
  include_examples 'ignored notice', params
@@ -217,7 +217,7 @@ RSpec.describe Airbrake::Notifier do
217
217
  end
218
218
 
219
219
  context "when the current env is not set and notify envs are present" do
220
- params = { ignore_environments: [:production, :development] }
220
+ params = { ignore_environments: %i[production development] }
221
221
 
222
222
  include_examples 'sent notice', params
223
223
  end
@@ -50,7 +50,7 @@ RSpec.describe "Airbrake::Notifier whitelist_keys" do
50
50
 
51
51
  context "when whitelisting with a Regexp" do
52
52
  let(:expected_body) do
53
- /"params":{"bingo":"bango","bongo":"\[Filtered\]","bash":"\[Filtered\]"}/
53
+ /"params":{"bingo":"bango","bongo":"\[Filtered\]","bash":"\[Filtered\]".*}/
54
54
  end
55
55
 
56
56
  include_examples(
@@ -62,7 +62,7 @@ RSpec.describe "Airbrake::Notifier whitelist_keys" do
62
62
 
63
63
  context "when whitelisting with a Symbol" do
64
64
  let(:expected_body) do
65
- /"params":{"bingo":"\[Filtered\]","bongo":"bish","bash":"\[Filtered\]"}/
65
+ /"params":{"bingo":"\[Filtered\]","bongo":"bish","bash":"\[Filtered\]".*}/
66
66
  end
67
67
 
68
68
  include_examples(
@@ -75,7 +75,7 @@ RSpec.describe "Airbrake::Notifier whitelist_keys" do
75
75
  context "when whitelisting with a String" do
76
76
  let(:expected_body) do
77
77
  /"params":{"bingo":"\[Filtered\]","bongo":"\[Filtered\]",
78
- "bash":"bosh","bbashh":"\[Filtered\]"}/x
78
+ "bash":"bosh","bbashh":"\[Filtered\]".*}/x
79
79
  end
80
80
 
81
81
  include_examples(
@@ -87,18 +87,20 @@ RSpec.describe "Airbrake::Notifier whitelist_keys" do
87
87
 
88
88
  context "when payload has a hash" do
89
89
  context "and it is a non-recursive hash" do
90
- let(:expected_body) { /"params":{"bingo":"\[Filtered\]","bongo":{"bish":"bash"}}/ }
90
+ let(:expected_body) do
91
+ /"params":{"bingo":"\[Filtered\]","bongo":{"bish":"bash"}.*}/
92
+ end
91
93
 
92
94
  include_examples(
93
95
  'whitelisting',
94
- %w(bongo bish),
96
+ %w[bongo bish],
95
97
  bingo: 'bango', bongo: { bish: 'bash' }
96
98
  )
97
99
  end
98
100
 
99
101
  context "and it is a recursive hash" do
100
102
  it "errors when nested hashes are not filtered" do
101
- whitelist = airbrake_params.merge(whitelist_keys: %w(bingo bango))
103
+ whitelist = airbrake_params.merge(whitelist_keys: %w[bingo bango])
102
104
  notifier = Airbrake::Notifier.new(whitelist)
103
105
 
104
106
  bongo = { bingo: {} }
@@ -129,7 +131,7 @@ RSpec.describe "Airbrake::Notifier whitelist_keys" do
129
131
 
130
132
  context "when there was a proc provided, which returns an array of keys" do
131
133
  let(:expected_body) do
132
- /"params":{"bingo":"\[Filtered\]","bongo":"bish","bash":"\[Filtered\]"}/
134
+ /"params":{"bingo":"\[Filtered\]","bongo":"bish","bash":"\[Filtered\]".*}/
133
135
  end
134
136
 
135
137
  include_examples(
@@ -141,7 +143,7 @@ RSpec.describe "Airbrake::Notifier whitelist_keys" do
141
143
 
142
144
  context "when there was a proc provided along with normal keys" do
143
145
  let(:expected_body) do
144
- /"params":{"bingo":"\[Filtered\]","bongo":"bish","bash":"bosh"}/
146
+ /"params":{"bingo":"\[Filtered\]","bongo":"bish","bash":"bosh".*}/
145
147
  end
146
148
 
147
149
  include_examples(
@@ -169,7 +171,7 @@ RSpec.describe "Airbrake::Notifier whitelist_keys" do
169
171
  notifier.notify_sync(ex, bingo: 'bango', bongo: 'bish')
170
172
 
171
173
  expect_a_request_with_body(
172
- /"params":{"bingo":"bango","bongo":"\[Filtered\]"}/
174
+ /"params":{"bingo":"bango","bongo":"\[Filtered\]".*}/
173
175
  )
174
176
  end
175
177
  end
@@ -189,14 +191,14 @@ RSpec.describe "Airbrake::Notifier whitelist_keys" do
189
191
  notifier.notify_sync(ex, bingo: 'bango', bongo: 'bish')
190
192
 
191
193
  expect_a_request_with_body(
192
- /"params":{"bingo":"\[Filtered\]","bongo":"\[Filtered\]"}/
194
+ /"params":{"bingo":"\[Filtered\]","bongo":"\[Filtered\]".*}/
193
195
  )
194
196
  end
195
197
  end
196
198
 
197
199
  describe "context/url" do
198
200
  let(:notifier) do
199
- Airbrake::Notifier.new(airbrake_params.merge(whitelist_keys: %w(bish)))
201
+ Airbrake::Notifier.new(airbrake_params.merge(whitelist_keys: %w[bish]))
200
202
  end
201
203
 
202
204
  context "given a standard URL" do
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+
2
3
  require 'spec_helper'
3
4
 
4
5
  RSpec.describe Airbrake::PayloadTruncator do
@@ -216,13 +217,13 @@ RSpec.describe Airbrake::PayloadTruncator do
216
217
 
217
218
  context "of short strings" do
218
219
  let(:params) do
219
- { bingo: %w(foo bar baz), bango: 'bongo', bish: 'bash' }
220
+ { bingo: %w[foo bar baz], bango: 'bongo', bish: 'bash' }
220
221
  end
221
222
 
222
223
  it "truncates long strings in the array, but not short ones" do
223
224
  @truncator.truncate_object(params)
224
225
  expect(params).
225
- to eq(bingo: %w(foo bar baz), bango: 'bongo', bish: 'bash')
226
+ to eq(bingo: %w[foo bar baz], bango: 'bongo', bish: 'bash')
226
227
  end
227
228
  end
228
229
 
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.0.0
4
+ version: 2.1.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: 2017-03-21 00:00:00.000000000 Z
11
+ date: 2017-04-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -116,9 +116,13 @@ files:
116
116
  - lib/airbrake-ruby/config/validator.rb
117
117
  - lib/airbrake-ruby/filter_chain.rb
118
118
  - lib/airbrake-ruby/filters.rb
119
+ - lib/airbrake-ruby/filters/gem_root_filter.rb
119
120
  - lib/airbrake-ruby/filters/keys_blacklist.rb
120
121
  - lib/airbrake-ruby/filters/keys_filter.rb
121
122
  - lib/airbrake-ruby/filters/keys_whitelist.rb
123
+ - lib/airbrake-ruby/filters/root_directory_filter.rb
124
+ - lib/airbrake-ruby/filters/system_exit_filter.rb
125
+ - lib/airbrake-ruby/filters/thread_filter.rb
122
126
  - lib/airbrake-ruby/nested_exception.rb
123
127
  - lib/airbrake-ruby/notice.rb
124
128
  - lib/airbrake-ruby/notifier.rb
@@ -133,6 +137,7 @@ files:
133
137
  - spec/config/validator_spec.rb
134
138
  - spec/config_spec.rb
135
139
  - spec/filter_chain_spec.rb
140
+ - spec/filters/thread_filter_spec.rb
136
141
  - spec/nested_exception_spec.rb
137
142
  - spec/notice_spec.rb
138
143
  - spec/notifier_spec.rb
@@ -174,6 +179,7 @@ test_files:
174
179
  - spec/config/validator_spec.rb
175
180
  - spec/config_spec.rb
176
181
  - spec/filter_chain_spec.rb
182
+ - spec/filters/thread_filter_spec.rb
177
183
  - spec/nested_exception_spec.rb
178
184
  - spec/notice_spec.rb
179
185
  - spec/notifier_spec/blacklist_keys_spec.rb