airbrake-ruby 2.0.0 → 2.1.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: 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