airbrake-ruby 1.4.6 → 1.5.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: 4e55d1ef72a4b324c33893e56abd9e92c661461c
4
- data.tar.gz: 14b98e0a8ba23394efd7c967add4ce0bdc93042c
3
+ metadata.gz: 2498350f956db613816b9cf8ae1579a01b0ca940
4
+ data.tar.gz: 3bafaf42dc712d226ac97b3ad5690f923ff49cc6
5
5
  SHA512:
6
- metadata.gz: 33b3db9de069c13caf56f7b63b423e4ef83730b6f40398e251e9bd075d043d5b1aada097884748394d315af95e76274841e616a610dfe3f99d8cb93eed22f83f
7
- data.tar.gz: 5f99f46b2ad687d9f9b3a11505c8189620a2f18ac63f4bb7fe5436c7b9aa88b3880f7adb0ca8f88edee299d92619e410c31f2915bff5861d3148551253c339eb
6
+ metadata.gz: 097a7a2681e0d28b020ea43a918b96ed0c89167a96d7b8146f27bac98682d95b61431ffe6eb1d78d278068b6321e4c28f196dec021c8a7fb7ed31c7e6465cc3d
7
+ data.tar.gz: 3cfdaaf798e0b85835126535434bb10bff78422b1b8890e924cf881b2b3843f0230eea43eaf6efdf0f9e3296941c2e85c217d71d6ed69b8caae3ae94be4baec7
data/lib/airbrake-ruby.rb CHANGED
@@ -7,6 +7,7 @@ require 'socket'
7
7
 
8
8
  require 'airbrake-ruby/version'
9
9
  require 'airbrake-ruby/config'
10
+ require 'airbrake-ruby/config/validator'
10
11
  require 'airbrake-ruby/sync_sender'
11
12
  require 'airbrake-ruby/async_sender'
12
13
  require 'airbrake-ruby/response'
@@ -26,14 +26,18 @@ module Airbrake
26
26
  ##
27
27
  # @return [Regexp] the pattern that matches JRuby Java stack frames, such
28
28
  # as org.jruby.ast.NewlineNode.interpret(NewlineNode.java:105)
29
- JAVA = /\A
30
- (?<function>.+) # Matches 'org.jruby.ast.NewlineNode.interpret
29
+ JAVA = %r{\A
30
+ (?<function>.+) # Matches 'org.jruby.ast.NewlineNode.interpret'
31
31
  \(
32
- (?<file>[^:]+) # Matches 'NewlineNode.java'
32
+ (?<file>
33
+ (?:uri:classloader:/.+(?=:)) # Matches '/META-INF/jruby.home/protocol.rb'
34
+ |
35
+ [^:]+ # Matches 'NewlineNode.java'
36
+ )
33
37
  :?
34
38
  (?<line>\d+)? # Matches '105'
35
39
  \)
36
- \z/x
40
+ \z}x
37
41
 
38
42
  ##
39
43
  # @return [Regexp] the pattern that tries to assume what a generic stack
@@ -73,6 +73,8 @@ module Airbrake
73
73
  # @param [Hash{Symbol=>Object}] user_config the hash to be used to build the
74
74
  # config
75
75
  def initialize(user_config = {})
76
+ @validator = Config::Validator.new(self)
77
+
76
78
  self.proxy = {}
77
79
  self.queue_size = 100
78
80
  self.workers = 1
@@ -130,8 +132,16 @@ module Airbrake
130
132
  # otherwise
131
133
  def valid?
132
134
  return true if ignored_environment?
133
- return false if project_id.to_i.zero?
134
- project_key.is_a?(String) && !project_key.empty?
135
+
136
+ return false unless @validator.valid_project_id?
137
+ return false unless @validator.valid_project_key?
138
+ return false unless @validator.valid_environment?
139
+
140
+ true
141
+ end
142
+
143
+ def validation_error_message
144
+ @validator.error_message
135
145
  end
136
146
 
137
147
  ##
@@ -0,0 +1,73 @@
1
+ module Airbrake
2
+ class Config
3
+ ##
4
+ # Validates values of {Airbrake::Config} options.
5
+ #
6
+ # @api private
7
+ # @since v1.5.0
8
+ class Validator
9
+ ##
10
+ # @return [String]
11
+ REQUIRED_KEY_MSG = ':project_key is required'.freeze
12
+
13
+ ##
14
+ # @return [String]
15
+ REQUIRED_ID_MSG = ':project_id is required'.freeze
16
+
17
+ ##
18
+ # @return [String]
19
+ WRONG_ENV_TYPE_MSG = "the 'environment' option must be configured " \
20
+ "with a Symbol (or String), but '%s' was provided: " \
21
+ "%s".freeze
22
+
23
+ ##
24
+ # @return [Array<Class>] the list of allowed types to configure the
25
+ # environment option
26
+ VALID_ENV_TYPES = [NilClass, String, Symbol].freeze
27
+
28
+ ##
29
+ # @return [String] error message, if validator was able to find any errors
30
+ # in the config
31
+ attr_reader :error_message
32
+
33
+ ##
34
+ # Validates given config and stores error message, if any errors were
35
+ # found.
36
+ #
37
+ # @param config [Airbrake::Config] the config to validate
38
+ def initialize(config)
39
+ @config = config
40
+ @error_message = nil
41
+ end
42
+
43
+ ##
44
+ # @return [Boolean]
45
+ def valid_project_id?
46
+ valid = @config.project_id.to_i > 0
47
+ @error_message = REQUIRED_ID_MSG unless valid
48
+ valid
49
+ end
50
+
51
+ ##
52
+ # @return [Boolean]
53
+ def valid_project_key?
54
+ valid = @config.project_key.is_a?(String) && !@config.project_key.empty?
55
+ @error_message = REQUIRED_KEY_MSG unless valid
56
+ valid
57
+ end
58
+
59
+ ##
60
+ # @return [Boolean]
61
+ def valid_environment?
62
+ environment = @config.environment
63
+ valid = VALID_ENV_TYPES.any? { |type| environment.is_a?(type) }
64
+
65
+ unless valid
66
+ @error_message = format(WRONG_ENV_TYPE_MSG, environment.class, environment)
67
+ end
68
+
69
+ valid
70
+ end
71
+ end
72
+ end
73
+ end
@@ -13,7 +13,10 @@ module Airbrake
13
13
  notice[:errors].each do |error|
14
14
  Gem.path.each do |gem_path|
15
15
  error[:backtrace].each do |frame|
16
- frame[:file].sub!(/\A#{gem_path}/, '[GEM_ROOT]'.freeze)
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]'.freeze)
17
20
  end
18
21
  end
19
22
  end
@@ -67,7 +70,8 @@ module Airbrake
67
70
  proc do |notice|
68
71
  notice[:errors].each do |error|
69
72
  error[:backtrace].each do |frame|
70
- frame[:file].sub!(/\A#{root_directory}/, '[PROJECT_ROOT]'.freeze)
73
+ next unless (file = frame[:file])
74
+ file.sub!(/\A#{root_directory}/, '[PROJECT_ROOT]'.freeze)
71
75
  end
72
76
  end
73
77
  end
@@ -32,8 +32,12 @@ module Airbrake
32
32
  def call(notice)
33
33
  FILTERABLE_KEYS.each { |key| filter_hash(notice[key]) }
34
34
 
35
- if notice[:context][:user] && should_filter?(:user)
36
- notice[:context][:user] = FILTERED
35
+ if notice[:context][:user]
36
+ if should_filter?(:user)
37
+ notice[:context][:user] = FILTERED
38
+ else
39
+ filter_hash(notice[:context][:user])
40
+ end
37
41
  end
38
42
 
39
43
  return unless notice[:context][:url]
@@ -2,7 +2,9 @@ module Airbrake
2
2
  ##
3
3
  # Represents a chunk of information that is meant to be either sent to
4
4
  # Airbrake or ignored completely.
5
+ # rubocop:disable Metrics/ClassLength
5
6
  class Notice
7
+ ##
6
8
  # @return [Hash{Symbol=>String}] the information about the notifier library
7
9
  NOTIFIER = {
8
10
  name: 'airbrake-ruby'.freeze,
@@ -66,6 +68,7 @@ module Airbrake
66
68
  session: {},
67
69
  params: params
68
70
  }
71
+ extract_custom_attributes(exception)
69
72
 
70
73
  @truncator = PayloadTruncator.new(PAYLOAD_MAX_SIZE, @config.logger)
71
74
  end
@@ -199,5 +202,30 @@ module Airbrake
199
202
 
200
203
  new_max_size
201
204
  end
205
+
206
+ def extract_custom_attributes(exception)
207
+ return unless exception.respond_to?(:to_airbrake)
208
+ attributes = nil
209
+
210
+ begin
211
+ attributes = exception.to_airbrake
212
+ rescue => ex
213
+ @config.logger.error(
214
+ "#{LOG_LABEL} #{exception.class}#to_airbrake failed: #{ex.class}: #{ex}"
215
+ )
216
+ end
217
+
218
+ return unless attributes
219
+
220
+ begin
221
+ @modifiable_payload.merge!(attributes)
222
+ rescue TypeError
223
+ @config.logger.error(
224
+ "#{LOG_LABEL} #{exception.class}#to_airbrake failed:" \
225
+ " #{attributes} must be a Hash"
226
+ )
227
+ end
228
+ end
202
229
  end
230
+ # rubocop:enable Metrics/ClassLength
203
231
  end
@@ -31,7 +31,7 @@ module Airbrake
31
31
  @config = (user_config.is_a?(Config) ? user_config : Config.new(user_config))
32
32
 
33
33
  unless @config.valid?
34
- raise Airbrake::Error, 'both :project_id and :project_key are required'
34
+ raise Airbrake::Error, @config.validation_error_message
35
35
  end
36
36
 
37
37
  @filter_chain = FilterChain.new(@config)
@@ -4,5 +4,5 @@
4
4
  module Airbrake
5
5
  ##
6
6
  # @return [String] the library version
7
- AIRBRAKE_RUBY_VERSION = '1.4.6'.freeze
7
+ AIRBRAKE_RUBY_VERSION = '1.5.0'.freeze
8
8
  end
@@ -76,6 +76,32 @@ RSpec.describe Airbrake::Backtrace do
76
76
  end
77
77
  end
78
78
 
79
+ context "JRuby classloader exceptions" do
80
+ let(:backtrace) do
81
+ # rubocop:disable Metrics/LineLength
82
+ ['uri_3a_classloader_3a_.META_minus_INF.jruby_dot_home.lib.ruby.stdlib.net.protocol.rbuf_fill(uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/net/protocol.rb:158)',
83
+ 'bin.processors.image_uploader.block in make_streams(bin/processors/image_uploader.rb:21)']
84
+ # rubocop:enable Metrics/LineLength
85
+ end
86
+
87
+ let(:parsed_backtrace) do
88
+ # rubocop:disable Metrics/LineLength
89
+ [{ file: 'uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/net/protocol.rb', line: 158, function: 'uri_3a_classloader_3a_.META_minus_INF.jruby_dot_home.lib.ruby.stdlib.net.protocol.rbuf_fill' },
90
+ { file: 'bin/processors/image_uploader.rb', line: 21, function: 'bin.processors.image_uploader.block in make_streams' }]
91
+ # rubocop:enable Metrics/LineLength
92
+ end
93
+
94
+ let(:ex) { JavaAirbrakeTestError.new.tap { |e| e.set_backtrace(backtrace) } }
95
+
96
+ it "returns a properly formatted array of hashes" do
97
+ allow(described_class).to receive(:java_exception?).and_return(true)
98
+
99
+ expect(
100
+ described_class.parse(ex, Logger.new('/dev/null'))
101
+ ).to eq(parsed_backtrace)
102
+ end
103
+ end
104
+
79
105
  context "generic backtrace" do
80
106
  context "when function is absent" do
81
107
  # rubocop:disable Metrics/LineLength
@@ -0,0 +1,189 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Airbrake::Config::Validator do
4
+ subject { described_class.new(config) }
5
+
6
+ describe "#valid_project_id?" do
7
+ context "when project id is zero" do
8
+ let(:config) { Airbrake::Config.new(project_id: 0) }
9
+
10
+ it "returns false" do
11
+ expect(subject.valid_project_id?).to be false
12
+ end
13
+
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/)
18
+ end
19
+ end
20
+
21
+ context "when project_id is a String" do
22
+ let(:config) { Airbrake::Config.new(project_id: '000') }
23
+
24
+ context "and when it's zero" do
25
+ it "returns false" do
26
+ expect(subject.valid_project_id?).to be false
27
+ end
28
+
29
+ it "sets correct error message" do
30
+ expect { subject.valid_project_id? }.
31
+ to change { subject.error_message }.
32
+ to(/:project_id is required/)
33
+ end
34
+ end
35
+
36
+ context "and when it consists of letters" do
37
+ let(:config) { Airbrake::Config.new(project_id: 'bingo') }
38
+
39
+ it "returns false" do
40
+ expect(subject.valid_project_id?).to be false
41
+ end
42
+
43
+ it "sets correct error message" do
44
+ expect { subject.valid_project_id? }.
45
+ to change { subject.error_message }.
46
+ to(/:project_id is required/)
47
+ end
48
+ end
49
+
50
+ context "and when it's numerical" do
51
+ let(:config) { Airbrake::Config.new(project_id: '123') }
52
+
53
+ it "returns true" do
54
+ expect(subject.valid_project_id?).to be true
55
+ end
56
+
57
+ it "doesn't set the error message" do
58
+ expect { subject.valid_project_id? }.not_to change { subject.error_message }
59
+ end
60
+ end
61
+ end
62
+
63
+ context "when project id is non-zero" do
64
+ let(:config) { Airbrake::Config.new(project_id: 123) }
65
+
66
+ it "returns true" do
67
+ expect(subject.valid_project_id?).to be true
68
+ end
69
+
70
+ it "doesn't set the error message" do
71
+ expect { subject.valid_project_id? }.not_to change { subject.error_message }
72
+ end
73
+ end
74
+ end
75
+
76
+ describe "#valid_project_key?" do
77
+ context "when it's a String" do
78
+ context "and when it's empty" do
79
+ let(:config) { Airbrake::Config.new(project_key: '') }
80
+
81
+ it "returns false" do
82
+ expect(subject.valid_project_key?).to be false
83
+ end
84
+
85
+ it "sets correct error message" do
86
+ expect { subject.valid_project_key? }.
87
+ to change { subject.error_message }.
88
+ to(/:project_key is required/)
89
+ end
90
+ end
91
+
92
+ context "and when it's non-empty" do
93
+ let(:config) { Airbrake::Config.new(project_key: '123abc') }
94
+
95
+ it "returns true" do
96
+ expect(subject.valid_project_key?).to be true
97
+ end
98
+
99
+ it "doesn't set the error message" do
100
+ expect { subject.valid_project_key? }.not_to change { subject.error_message }
101
+ end
102
+ end
103
+ end
104
+
105
+ context "when it's not a String" do
106
+ let(:config) { Airbrake::Config.new(project_key: 123) }
107
+
108
+ it "returns false" do
109
+ expect(subject.valid_project_key?).to be false
110
+ end
111
+
112
+ it "sets correct error message" do
113
+ expect { subject.valid_project_key? }.
114
+ to change { subject.error_message }.
115
+ to(/:project_key is required/)
116
+ end
117
+ end
118
+ end
119
+
120
+ describe "#valid_environment?" do
121
+ context "when config.environment is not set" do
122
+ let(:config) { Airbrake::Config.new }
123
+
124
+ it "returns true" do
125
+ expect(subject.valid_environment?).to be true
126
+ end
127
+
128
+ it "doesn't set the error message" do
129
+ expect { subject.valid_environment? }.not_to change { subject.error_message }
130
+ end
131
+ end
132
+
133
+ context "when config.environment is set" do
134
+ context "and when it is not a Symbol or String" do
135
+ let(:config) { Airbrake::Config.new(environment: 123) }
136
+
137
+ it "returns false" do
138
+ expect(subject.valid_environment?).to be false
139
+ end
140
+
141
+ 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/)
145
+ end
146
+ end
147
+
148
+ context "and when it is a Symbol" do
149
+ let(:config) { Airbrake::Config.new(environment: :bingo) }
150
+
151
+ it "returns true" do
152
+ expect(subject.valid_environment?).to be true
153
+ end
154
+
155
+ it "doesn't set the error message" do
156
+ expect { subject.valid_environment? }.not_to change { subject.error_message }
157
+ end
158
+ end
159
+
160
+ context "and when it is a String" do
161
+ let(:config) { Airbrake::Config.new(environment: 'bingo') }
162
+
163
+ it "returns true" do
164
+ expect(subject.valid_environment?).to be true
165
+ end
166
+
167
+ it "doesn't set the error message" do
168
+ expect { subject.valid_environment? }.not_to change { subject.error_message }
169
+ end
170
+ end
171
+
172
+ context "and when it is kind of a String" do
173
+ let(:string_inquirer) { Class.new(String) }
174
+
175
+ let(:config) do
176
+ Airbrake::Config.new(environment: string_inquirer.new('bingo'))
177
+ end
178
+
179
+ it "returns true" do
180
+ expect(subject.valid_environment?).to be true
181
+ end
182
+
183
+ it "doesn't set the error message" do
184
+ expect { subject.valid_environment? }.not_to change { subject.error_message }
185
+ end
186
+ end
187
+ end
188
+ end
189
+ end
data/spec/config_spec.rb CHANGED
@@ -155,6 +155,22 @@ RSpec.describe Airbrake::Config do
155
155
  expect(config).not_to be_valid
156
156
  end
157
157
  end
158
+
159
+ context "when the environment value is not a String" do
160
+ let(:out) { StringIO.new }
161
+ let(:config) { described_class.new(logger: Logger.new(out)) }
162
+
163
+ before do
164
+ config.project_id = 123
165
+ config.project_key = '321'
166
+
167
+ config.environment = ['bingo']
168
+ end
169
+
170
+ it "returns false" do
171
+ expect(config).not_to be_valid
172
+ end
173
+ end
158
174
  end
159
175
 
160
176
  describe "#ignored_environment?" do
@@ -152,6 +152,42 @@ RSpec.describe Airbrake::FilterChain do
152
152
  to(change { notice.ignored? }.from(false).to(true))
153
153
  end
154
154
  end
155
+
156
+ context "gem root filter" do
157
+ let(:ex) do
158
+ AirbrakeTestError.new.tap do |error|
159
+ error.set_backtrace(['(unparseable/frame.rb:23)'])
160
+ end
161
+ end
162
+
163
+ it "does not filter file if it is nil" do
164
+ config.logger = Logger.new('/dev/null')
165
+ notice = Airbrake::Notice.new(config, ex)
166
+
167
+ expect(notice[:errors].first[:file]).to be_nil
168
+ expect { @chain.refine(notice) }.
169
+ not_to change { notice[:errors].first[:file] }
170
+ end
171
+ end
172
+
173
+ context "root directory filter" do
174
+ let(:ex) do
175
+ AirbrakeTestError.new.tap do |error|
176
+ error.set_backtrace(['(unparseable/frame.rb:23)'])
177
+ end
178
+ end
179
+
180
+ it "does not filter file if it is nil" do
181
+ config.logger = Logger.new('/dev/null')
182
+ config.root_directory = '/bingo/bango'
183
+ notice = Airbrake::Notice.new(config, ex)
184
+ filter_chain = described_class.new(config)
185
+
186
+ expect(notice[:errors].first[:file]).to be_nil
187
+ expect { filter_chain.refine(notice) }.
188
+ not_to change { notice[:errors].first[:file] }
189
+ end
190
+ end
155
191
  end
156
192
  end
157
193
  end
data/spec/notice_spec.rb CHANGED
@@ -5,6 +5,75 @@ RSpec.describe Airbrake::Notice do
5
5
  described_class.new(Airbrake::Config.new, AirbrakeTestError.new, bingo: '1')
6
6
  end
7
7
 
8
+ describe "#new" do
9
+ let(:params) do
10
+ { bingo: 'bango', bongo: 'bish' }
11
+ end
12
+
13
+ let(:ex) { airbrake_exception_class.new(params) }
14
+
15
+ context "given an exception class, which supports #to_airbrake" do
16
+ context "and when #to_airbrake returns a non-Hash object" do
17
+ let(:airbrake_exception_class) do
18
+ Class.new(AirbrakeTestError) do
19
+ def to_airbrake
20
+ Object.new
21
+ end
22
+ end
23
+ end
24
+
25
+ it "rescues the error, logs it and doesn't modify the payload" do
26
+ out = StringIO.new
27
+ config = Airbrake::Config.new(logger: Logger.new(out))
28
+ notice = nil
29
+
30
+ expect { notice = described_class.new(config, ex) }.not_to raise_error
31
+ expect(out.string).to match(/#to_airbrake failed:.+Object.+must be a Hash/)
32
+ expect(notice[:params]).to be_empty
33
+ end
34
+ end
35
+
36
+ context "and when #to_airbrake errors out" do
37
+ let(:airbrake_exception_class) do
38
+ Class.new(AirbrakeTestError) do
39
+ def to_airbrake
40
+ 1 / 0
41
+ end
42
+ end
43
+ end
44
+
45
+ it "rescues the error, logs it and doesn't modify the payload" do
46
+ out = StringIO.new
47
+ config = Airbrake::Config.new(logger: Logger.new(out))
48
+ notice = nil
49
+
50
+ expect { notice = described_class.new(config, ex) }.not_to raise_error
51
+ expect(out.string).to match(/#to_airbrake failed: ZeroDivisionError/)
52
+ expect(notice[:params]).to be_empty
53
+ end
54
+ end
55
+
56
+ context "and when #to_airbrake succeeds" do
57
+ let(:airbrake_exception_class) do
58
+ Class.new(AirbrakeTestError) do
59
+ def initialize(params)
60
+ @params = params
61
+ end
62
+
63
+ def to_airbrake
64
+ { params: @params }
65
+ end
66
+ end
67
+ end
68
+
69
+ it "merges the parameters with the notice" do
70
+ notice = described_class.new(Airbrake::Config.new, ex)
71
+ expect(notice[:params]).to eq(params)
72
+ end
73
+ end
74
+ end
75
+ end
76
+
8
77
  describe "#to_json" do
9
78
  context "app_version" do
10
79
  context "when missing" do
@@ -30,21 +30,18 @@ RSpec.describe Airbrake::Notifier do
30
30
  describe "#new" do
31
31
  context "raises error if" do
32
32
  example ":project_id is not provided" do
33
- expect { described_class.new(project_id: project_id) }.
34
- to raise_error(Airbrake::Error,
35
- 'both :project_id and :project_key are required')
33
+ expect { described_class.new(project_key: project_key) }.
34
+ to raise_error(Airbrake::Error, ':project_id is required')
36
35
  end
37
36
 
38
37
  example ":project_key is not provided" do
39
- expect { described_class.new(project_key: project_key) }.
40
- to raise_error(Airbrake::Error,
41
- 'both :project_id and :project_key are required')
38
+ expect { described_class.new(project_id: project_id) }.
39
+ to raise_error(Airbrake::Error, ':project_key is required')
42
40
  end
43
41
 
44
42
  example "neither :project_id nor :project_key are provided" do
45
43
  expect { described_class.new({}) }.
46
- to raise_error(Airbrake::Error,
47
- 'both :project_id and :project_key are required')
44
+ to raise_error(Airbrake::Error, ':project_id is required')
48
45
  end
49
46
  end
50
47
 
@@ -571,6 +568,17 @@ RSpec.describe Airbrake::Notifier do
571
568
 
572
569
  expect_a_request_with_body(/"user":"\[Filtered\]"/)
573
570
  end
571
+
572
+ it "filters out individual user fields" do
573
+ @airbrake.blacklist_keys('name')
574
+
575
+ notice = @airbrake.build_notice(ex)
576
+ notice[:context][:user] = { id: 1337, name: 'Bingo Bango' }
577
+
578
+ @airbrake.notify_sync(notice)
579
+
580
+ expect_a_request_with_body(/"user":{"id":1337,"name":"\[Filtered\]"}/)
581
+ end
574
582
  end
575
583
 
576
584
  describe "#whitelist_keys" do
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: 1.4.6
4
+ version: 1.5.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: 2016-08-18 00:00:00.000000000 Z
11
+ date: 2016-09-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -99,6 +99,7 @@ files:
99
99
  - lib/airbrake-ruby/async_sender.rb
100
100
  - lib/airbrake-ruby/backtrace.rb
101
101
  - lib/airbrake-ruby/config.rb
102
+ - lib/airbrake-ruby/config/validator.rb
102
103
  - lib/airbrake-ruby/filter_chain.rb
103
104
  - lib/airbrake-ruby/filters.rb
104
105
  - lib/airbrake-ruby/filters/keys_blacklist.rb
@@ -114,6 +115,7 @@ files:
114
115
  - spec/airbrake_spec.rb
115
116
  - spec/async_sender_spec.rb
116
117
  - spec/backtrace_spec.rb
118
+ - spec/config/validator_spec.rb
117
119
  - spec/config_spec.rb
118
120
  - spec/filter_chain_spec.rb
119
121
  - spec/nested_exception_spec.rb
@@ -151,6 +153,7 @@ test_files:
151
153
  - spec/airbrake_spec.rb
152
154
  - spec/async_sender_spec.rb
153
155
  - spec/backtrace_spec.rb
156
+ - spec/config/validator_spec.rb
154
157
  - spec/config_spec.rb
155
158
  - spec/filter_chain_spec.rb
156
159
  - spec/nested_exception_spec.rb