airbrake-ruby 6.0.1 → 6.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/lib/airbrake-ruby/config/processor.rb +6 -0
  3. data/lib/airbrake-ruby/config.rb +3 -3
  4. data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +1 -1
  5. data/lib/airbrake-ruby/filters/git_repository_filter.rb +7 -1
  6. data/lib/airbrake-ruby/filters/sql_filter.rb +6 -6
  7. data/lib/airbrake-ruby/nested_exception.rb +10 -1
  8. data/lib/airbrake-ruby/notice.rb +5 -3
  9. data/lib/airbrake-ruby/performance_notifier.rb +38 -38
  10. data/lib/airbrake-ruby/stat.rb +1 -1
  11. data/lib/airbrake-ruby/time_truncate.rb +2 -2
  12. data/lib/airbrake-ruby/version.rb +1 -1
  13. data/lib/airbrake-ruby.rb +21 -21
  14. metadata +6 -123
  15. data/spec/airbrake_spec.rb +0 -522
  16. data/spec/async_sender_spec.rb +0 -65
  17. data/spec/backtrace_spec.rb +0 -430
  18. data/spec/benchmark_spec.rb +0 -35
  19. data/spec/code_hunk_spec.rb +0 -124
  20. data/spec/config/processor_spec.rb +0 -151
  21. data/spec/config/validator_spec.rb +0 -204
  22. data/spec/config_spec.rb +0 -188
  23. data/spec/context_spec.rb +0 -54
  24. data/spec/deploy_notifier_spec.rb +0 -50
  25. data/spec/file_cache_spec.rb +0 -35
  26. data/spec/filter_chain_spec.rb +0 -124
  27. data/spec/filters/context_filter_spec.rb +0 -32
  28. data/spec/filters/dependency_filter_spec.rb +0 -14
  29. data/spec/filters/exception_attributes_filter_spec.rb +0 -52
  30. data/spec/filters/gem_root_filter_spec.rb +0 -44
  31. data/spec/filters/git_last_checkout_filter_spec.rb +0 -61
  32. data/spec/filters/git_repository_filter.rb +0 -61
  33. data/spec/filters/git_revision_filter_spec.rb +0 -126
  34. data/spec/filters/keys_allowlist_spec.rb +0 -204
  35. data/spec/filters/keys_blocklist_spec.rb +0 -242
  36. data/spec/filters/root_directory_filter_spec.rb +0 -39
  37. data/spec/filters/sql_filter_spec.rb +0 -274
  38. data/spec/filters/system_exit_filter_spec.rb +0 -16
  39. data/spec/filters/thread_filter_spec.rb +0 -281
  40. data/spec/fixtures/notroot.txt +0 -7
  41. data/spec/fixtures/project_root/code.rb +0 -221
  42. data/spec/fixtures/project_root/empty_file.rb +0 -0
  43. data/spec/fixtures/project_root/long_line.txt +0 -1
  44. data/spec/fixtures/project_root/short_file.rb +0 -3
  45. data/spec/fixtures/project_root/vendor/bundle/ignored_file.rb +0 -5
  46. data/spec/helpers.rb +0 -9
  47. data/spec/ignorable_spec.rb +0 -14
  48. data/spec/inspectable_spec.rb +0 -45
  49. data/spec/loggable_spec.rb +0 -17
  50. data/spec/monotonic_time_spec.rb +0 -25
  51. data/spec/nested_exception_spec.rb +0 -73
  52. data/spec/notice_notifier/options_spec.rb +0 -269
  53. data/spec/notice_notifier_spec.rb +0 -361
  54. data/spec/notice_spec.rb +0 -300
  55. data/spec/performance_breakdown_spec.rb +0 -11
  56. data/spec/performance_notifier_spec.rb +0 -645
  57. data/spec/promise_spec.rb +0 -203
  58. data/spec/query_spec.rb +0 -11
  59. data/spec/queue_spec.rb +0 -18
  60. data/spec/remote_settings/callback_spec.rb +0 -162
  61. data/spec/remote_settings/settings_data_spec.rb +0 -348
  62. data/spec/remote_settings_spec.rb +0 -201
  63. data/spec/request_spec.rb +0 -9
  64. data/spec/response_spec.rb +0 -110
  65. data/spec/spec_helper.rb +0 -100
  66. data/spec/stashable_spec.rb +0 -23
  67. data/spec/stat_spec.rb +0 -39
  68. data/spec/sync_sender_spec.rb +0 -168
  69. data/spec/tdigest_spec.rb +0 -235
  70. data/spec/thread_pool_spec.rb +0 -196
  71. data/spec/time_truncate_spec.rb +0 -15
  72. data/spec/timed_trace_spec.rb +0 -127
  73. data/spec/truncator_spec.rb +0 -267
@@ -1,221 +0,0 @@
1
- module Airbrake
2
- ##
3
- # Represents a chunk of information that is meant to be either sent to
4
- # Airbrake or ignored completely.
5
- #
6
- # @since v1.0.0
7
- class Notice
8
- ##
9
- # @return [Hash{Symbol=>String}] the information about the notifier library
10
- NOTIFIER = {
11
- name: 'airbrake-ruby'.freeze,
12
- version: Airbrake::AIRBRAKE_RUBY_VERSION,
13
- url: 'https://github.com/airbrake/airbrake-ruby'.freeze,
14
- }.freeze
15
-
16
- ##
17
- # @return [Hash{Symbol=>String,Hash}] the information to be displayed in the
18
- # Context tab in the dashboard
19
- CONTEXT = {
20
- os: RUBY_PLATFORM,
21
- language: "#{RUBY_ENGINE}/#{RUBY_VERSION}".freeze,
22
- notifier: NOTIFIER,
23
- }.freeze
24
-
25
- ##
26
- # @return [Integer] the maxium size of the JSON payload in bytes
27
- MAX_NOTICE_SIZE = 64000
28
-
29
- ##
30
- # @return [Integer] the maximum size of hashes, arrays and strings in the
31
- # notice.
32
- PAYLOAD_MAX_SIZE = 10000
33
-
34
- ##
35
- # @return [Array<StandardError>] the list of possible exceptions that might
36
- # be raised when an object is converted to JSON
37
- JSON_EXCEPTIONS = [
38
- IOError,
39
- NotImplementedError,
40
- JSON::GeneratorError,
41
- Encoding::UndefinedConversionError,
42
- ].freeze
43
-
44
- # @return [Array<Symbol>] the list of keys that can be be overwritten with
45
- # {Airbrake::Notice#[]=}
46
- WRITABLE_KEYS = %i[notifier context environment session params].freeze
47
-
48
- ##
49
- # @return [Array<Symbol>] parts of a Notice's payload that can be modified
50
- # by the truncator
51
- TRUNCATABLE_KEYS = %i[errors environment session params].freeze
52
-
53
- ##
54
- # @return [String] the name of the host machine
55
- HOSTNAME = Socket.gethostname.freeze
56
-
57
- ##
58
- # @return [String]
59
- DEFAULT_SEVERITY = 'error'.freeze
60
-
61
- ##
62
- # @since v1.7.0
63
- # @return [Hash{Symbol=>Object}] the hash with arbitrary objects to be used
64
- # in filters
65
- attr_reader :stash
66
-
67
- def initialize(config, exception, params = {})
68
- @config = config
69
-
70
- @payload = {
71
- errors: NestedException.new(config, exception).as_json,
72
- context: context,
73
- environment: {
74
- program_name: $PROGRAM_NAME,
75
- },
76
- session: {},
77
- params: params,
78
- }
79
- @stash = { exception: exception }
80
- @truncator = Airbrake::Truncator.new(PAYLOAD_MAX_SIZE)
81
-
82
- extract_custom_attributes(exception)
83
- end
84
-
85
- ##
86
- # Converts the notice to JSON. Calls +to_json+ on each object inside
87
- # notice's payload. Truncates notices, JSON representation of which is
88
- # bigger than {MAX_NOTICE_SIZE}.
89
- #
90
- # @return [Hash{String=>String}, nil]
91
- def to_json
92
- loop do
93
- begin
94
- json = @payload.to_json
95
- rescue *JSON_EXCEPTIONS => ex
96
- @config.logger.debug("#{LOG_LABEL} `notice.to_json` failed: #{ex.class}: #{ex}")
97
- else
98
- return json if json && json.bytesize <= MAX_NOTICE_SIZE
99
- end
100
-
101
- break if truncate == 0
102
- end
103
- end
104
-
105
- ##
106
- # Ignores a notice. Ignored notices never reach the Airbrake dashboard.
107
- #
108
- # @return [void]
109
- # @see #ignored?
110
- # @note Ignored noticed can't be unignored
111
- def ignore!
112
- @payload = nil
113
- end
114
-
115
- ##
116
- # Checks whether the notice was ignored.
117
- #
118
- # @return [Boolean]
119
- # @see #ignore!
120
- def ignored?
121
- @payload.nil?
122
- end
123
-
124
- ##
125
- # Reads a value from notice's payload.
126
- # @return [Object]
127
- #
128
- # @raise [Airbrake::Error] if the notice is ignored
129
- def [](key)
130
- raise_if_ignored
131
- @payload[key]
132
- end
133
-
134
- ##
135
- # Writes a value to the payload hash. Restricts unrecognized
136
- # writes.
137
- # @example
138
- # notice[:params][:my_param] = 'foobar'
139
- #
140
- # @return [void]
141
- # @raise [Airbrake::Error] if the notice is ignored
142
- # @raise [Airbrake::Error] if the +key+ is not recognized
143
- # @raise [Airbrake::Error] if the root value is not a Hash
144
- def []=(key, value)
145
- raise_if_ignored
146
-
147
- unless WRITABLE_KEYS.include?(key)
148
- raise Airbrake::Error,
149
- ":#{key} is not recognized among #{WRITABLE_KEYS}"
150
- end
151
-
152
- unless value.respond_to?(:to_hash)
153
- raise Airbrake::Error, "Got #{value.class} value, wanted a Hash"
154
- end
155
-
156
- @payload[key] = value.to_hash
157
- end
158
-
159
- private
160
-
161
- def context
162
- {
163
- version: @config.app_version,
164
- # We ensure that root_directory is always a String, so it can always be
165
- # converted to JSON in a predictable manner (when it's a Pathname and in
166
- # Rails environment, it converts to unexpected JSON).
167
- rootDirectory: @config.root_directory.to_s,
168
- environment: @config.environment,
169
-
170
- # Make sure we always send hostname.
171
- hostname: HOSTNAME,
172
-
173
- severity: DEFAULT_SEVERITY,
174
- }.merge(CONTEXT).delete_if { |_key, val| val.nil? || val.empty? }
175
- end
176
-
177
- def raise_if_ignored
178
- return unless ignored?
179
- raise Airbrake::Error, 'cannot access ignored notice'
180
- end
181
-
182
- def truncate
183
- TRUNCATABLE_KEYS.each { |key| @truncator.truncate(self[key]) }
184
-
185
- new_max_size = @truncator.reduce_max_size
186
- if new_max_size == 0
187
- @config.logger.error(
188
- "#{LOG_LABEL} truncation failed. File an issue at " \
189
- "https://github.com/airbrake/airbrake-ruby " \
190
- "and attach the following payload: #{@payload}",
191
- )
192
- end
193
-
194
- new_max_size
195
- end
196
-
197
- def extract_custom_attributes(exception)
198
- return unless exception.respond_to?(:to_airbrake)
199
- attributes = nil
200
-
201
- begin
202
- attributes = exception.to_airbrake
203
- rescue StandardError => ex
204
- @config.logger.error(
205
- "#{LOG_LABEL} #{exception.class}#to_airbrake failed: #{ex.class}: #{ex}",
206
- )
207
- end
208
-
209
- return unless attributes
210
-
211
- begin
212
- @payload.merge!(attributes)
213
- rescue TypeError
214
- @config.logger.error(
215
- "#{LOG_LABEL} #{exception.class}#to_airbrake failed:" \
216
- " #{attributes} must be a Hash",
217
- )
218
- end
219
- end
220
- end
221
- end
File without changes
@@ -1 +0,0 @@
1
- loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong line
@@ -1,3 +0,0 @@
1
- module Banana
2
- attr_reader :bingo
3
- end
@@ -1,5 +0,0 @@
1
- module IgnoredFile
2
- def ignore_me
3
- puts 'Anybody here?'
4
- end
5
- end
data/spec/helpers.rb DELETED
@@ -1,9 +0,0 @@
1
- module Helpers
2
- def fixture_path(filename)
3
- File.expand_path(File.join('spec', 'fixtures', filename))
4
- end
5
-
6
- def project_root_path(filename)
7
- fixture_path(File.join('project_root', filename))
8
- end
9
- end
@@ -1,14 +0,0 @@
1
- RSpec.describe Airbrake::Ignorable do
2
- let(:klass) do
3
- mod = subject
4
- Class.new { include(mod) }
5
- end
6
-
7
- it "ignores includee" do
8
- instance = klass.new
9
- expect(instance).not_to be_ignored
10
-
11
- instance.ignore!
12
- expect(instance).to be_ignored
13
- end
14
- end
@@ -1,45 +0,0 @@
1
- RSpec.describe Airbrake::Inspectable do
2
- let(:klass) do
3
- mod = subject
4
- Class.new do
5
- include(mod)
6
-
7
- def initialize
8
- @config = Airbrake::Config.new
9
- @filter_chain = nil
10
- end
11
- end
12
- end
13
-
14
- describe "#inspect" do
15
- it "displays object information" do
16
- instance = klass.new
17
- expect(instance.inspect).to match(/
18
- #<:0x\w+\s
19
- project_id=""\s
20
- project_key=""\s
21
- host="http.+"\s
22
- filter_chain=nil>
23
- /x)
24
- end
25
- end
26
-
27
- describe "#pretty_print" do
28
- it "displays object information in a beautiful way" do
29
- q = PP.new
30
-
31
- instance = klass.new
32
- # Guarding is needed to fix JRuby failure:
33
- # NoMethodError: undefined method `[]' for nil:NilClass
34
- q.guard_inspect_key { instance.pretty_print(q) }
35
-
36
- expect(q.output).to match(/
37
- #<:0x\w+\s
38
- project_id=""\s
39
- project_key=""\s
40
- host="http.+"\s
41
- filter_chain=nil
42
- /x)
43
- end
44
- end
45
- end
@@ -1,17 +0,0 @@
1
- RSpec.describe Airbrake::Loggable do
2
- describe ".instance" do
3
- it "returns a logger" do
4
- expect(described_class.instance).to be_a(Logger)
5
- end
6
- end
7
-
8
- describe "#logger" do
9
- subject(:class_with_logger) do
10
- Class.new { include Airbrake::Loggable }.new
11
- end
12
-
13
- it "returns a logger that has Logger::WARN severity" do
14
- expect(class_with_logger.logger.level).to eq(Logger::WARN)
15
- end
16
- end
17
- end
@@ -1,25 +0,0 @@
1
- RSpec.describe Airbrake::MonotonicTime do
2
- subject(:monotonic_time) { described_class }
3
-
4
- describe ".time_in_ms" do
5
- it "returns monotonic time in milliseconds" do
6
- expect(monotonic_time.time_in_ms).to be_a(Float)
7
- end
8
-
9
- it "always returns time in the future" do
10
- old_time = monotonic_time.time_in_ms
11
- expect(monotonic_time.time_in_ms).to be > old_time
12
- end
13
- end
14
-
15
- describe ".time_in_s" do
16
- it "returns monotonic time in seconds" do
17
- expect(monotonic_time.time_in_s).to be_a(Float)
18
- end
19
-
20
- it "always returns time in the future" do
21
- old_time = monotonic_time.time_in_s
22
- expect(monotonic_time.time_in_s).to be > old_time
23
- end
24
- end
25
- end
@@ -1,73 +0,0 @@
1
- RSpec.describe Airbrake::NestedException do
2
- describe "#as_json" do
3
- context "given exceptions with backtraces" do
4
- # rubocop:disable RSpec/MultipleExpectations
5
- it "unwinds nested exceptions" do
6
- begin
7
- raise AirbrakeTestError
8
- rescue AirbrakeTestError
9
- Ruby21Error.raise_error('bingo')
10
- end
11
- rescue Ruby21Error => ex
12
- nested_exception = described_class.new(ex)
13
- exceptions = nested_exception.as_json
14
-
15
- expect(exceptions.size).to eq(2)
16
- expect(exceptions[0][:message]).to eq('bingo')
17
- expect(exceptions[1][:message]).to eq('App crashed!')
18
- expect(exceptions[0][:backtrace]).not_to be_empty
19
- expect(exceptions[1][:backtrace]).not_to be_empty
20
- end
21
- # rubocop:enable RSpec/MultipleExpectations
22
-
23
- # rubocop:disable RSpec/MultipleExpectations
24
- it "unwinds no more than 3 nested exceptions" do
25
- begin
26
- raise AirbrakeTestError
27
- rescue AirbrakeTestError
28
- begin
29
- Ruby21Error.raise_error('bongo')
30
- rescue Ruby21Error
31
- begin
32
- Ruby21Error.raise_error('bango')
33
- rescue Ruby21Error
34
- Ruby21Error.raise_error('bingo')
35
- end
36
- end
37
- end
38
- rescue Ruby21Error => ex
39
- nested_exception = described_class.new(ex)
40
- exceptions = nested_exception.as_json
41
-
42
- expect(exceptions.size).to eq(3)
43
- expect(exceptions[0][:message]).to eq('bingo')
44
- expect(exceptions[1][:message]).to eq('bango')
45
- expect(exceptions[2][:message]).to eq('bongo')
46
- expect(exceptions[0][:backtrace]).not_to be_empty
47
- expect(exceptions[1][:backtrace]).not_to be_empty
48
- end
49
- # rubocop:enable RSpec/MultipleExpectations
50
- end
51
-
52
- context "given exceptions without backtraces" do
53
- # rubocop:disable RSpec/MultipleExpectations
54
- it "sets backtrace to nil" do
55
- begin
56
- raise AirbrakeTestError
57
- rescue AirbrakeTestError => ex2
58
- ex2.set_backtrace([])
59
- Ruby21Error.raise_error('bingo')
60
- end
61
- rescue Ruby21Error => ex1
62
- ex1.set_backtrace([])
63
- nested_exception = described_class.new(ex1)
64
- exceptions = nested_exception.as_json
65
-
66
- expect(exceptions.size).to eq(2)
67
- expect(exceptions[0][:backtrace]).to be_empty
68
- expect(exceptions[1][:backtrace]).to be_empty
69
- end
70
- # rubocop:enable RSpec/MultipleExpectations
71
- end
72
- end
73
- end
@@ -1,269 +0,0 @@
1
- RSpec.describe Airbrake::NoticeNotifier do
2
- subject(:notice_notifier) { described_class.new }
3
-
4
- let(:project_id) { 105138 }
5
- let(:project_key) { 'fd04e13d806a90f96614ad8e529b2822' }
6
- let(:localhost) { 'http://localhost:8080' }
7
-
8
- let(:endpoint) do
9
- "https://api.airbrake.io/api/v3/projects/#{project_id}/notices"
10
- end
11
-
12
- let(:params) { {} }
13
- let(:ex) { AirbrakeTestError.new }
14
-
15
- before do
16
- stub_request(:post, endpoint).to_return(status: 201, body: '{}')
17
-
18
- Airbrake::Config.instance = Airbrake::Config.new(
19
- project_id: project_id,
20
- project_key: project_key,
21
- )
22
- end
23
-
24
- describe "options" do
25
- describe ":host" do
26
- context "when custom" do
27
- shared_examples 'endpoint' do |host, endpoint, title|
28
- before { Airbrake::Config.instance.merge(host: host) }
29
-
30
- example(title) do
31
- stub_request(:post, endpoint).to_return(status: 201, body: '{}')
32
- notice_notifier.notify_sync(ex)
33
-
34
- expect(a_request(:post, endpoint)).to have_been_made.once
35
- end
36
- end
37
-
38
- path = '/api/v3/projects/105138/notices'
39
-
40
- context "given a full host with port" do
41
- include_examples('endpoint', localhost = 'http://localhost:8080',
42
- URI.join(localhost, path),
43
- "sends notices to the specified host's endpoint")
44
- end
45
-
46
- context "given a full host" do
47
- include_examples('endpoint', localhost = 'http://localhost',
48
- URI.join(localhost, path),
49
- "assumes port 80 by default")
50
- end
51
-
52
- context "given a host without scheme" do
53
- include_examples 'endpoint', localhost = 'localhost:8080',
54
- URI.join("https://#{localhost}", path),
55
- "assumes https by default"
56
- end
57
-
58
- context "given only hostname" do
59
- include_examples 'endpoint', localhost = 'localhost',
60
- URI.join("https://#{localhost}", path),
61
- "assumes https and port 80 by default"
62
- end
63
- end
64
- end
65
-
66
- describe ":root_directory" do
67
- before do
68
- notice_notifier.add_filter(
69
- Airbrake::Filters::RootDirectoryFilter.new('/home/kyrylo/code'),
70
- )
71
- end
72
-
73
- it "filters out frames" do
74
- notice_notifier.notify_sync(ex)
75
-
76
- expect(
77
- a_request(:post, endpoint)
78
- .with(body: %r|{"file":"/PROJECT_ROOT/airbrake/ruby/spec/airbrake_spec.+|),
79
- ).to have_been_made.once
80
- end
81
-
82
- context "when present and is a" do
83
- shared_examples 'root directory' do |dir|
84
- before { Airbrake::Config.instance.merge(root_directory: dir) }
85
-
86
- it "being included into the notice's payload" do
87
- notice_notifier.notify_sync(ex)
88
- expect(
89
- a_request(:post, endpoint)
90
- .with(body: %r{"rootDirectory":"/bingo/bango"}),
91
- ).to have_been_made.once
92
- end
93
- end
94
-
95
- context "String" do
96
- include_examples 'root directory', '/bingo/bango'
97
- end
98
-
99
- context "Pathname" do
100
- include_examples 'root directory', Pathname.new('/bingo/bango')
101
- end
102
- end
103
- end
104
-
105
- # rubocop:disable RSpec/MultipleMemoizedHelpers
106
- describe ":proxy" do
107
- let(:proxy) do
108
- WEBrick::HTTPServer.new(
109
- Port: 0,
110
- Logger: WEBrick::Log.new('/dev/null'),
111
- AccessLog: [],
112
- )
113
- end
114
-
115
- let(:requests) { Queue.new }
116
-
117
- let(:proxy_params) do
118
- { host: 'localhost',
119
- port: proxy.config[:Port],
120
- user: 'user',
121
- password: 'password' }
122
- end
123
-
124
- before do
125
- Airbrake::Config.instance.merge(
126
- proxy: proxy_params,
127
- host: "http://localhost:#{proxy.config[:Port]}",
128
- )
129
-
130
- proxy.mount_proc '/' do |req, res|
131
- requests << req
132
- res.status = 201
133
- res.body = "OK\n"
134
- end
135
-
136
- Thread.new { proxy.start }
137
- end
138
-
139
- after { proxy.stop }
140
-
141
- it "is being used if configured" do
142
- if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.6.0")
143
- skip(
144
- "We use Webmock 2, which doesn't support Ruby 2.6+. It's " \
145
- "safe to run this test on 2.6+ once we upgrade to Webmock 3.5+",
146
- )
147
- end
148
- notice_notifier.notify_sync(ex)
149
-
150
- proxied_request = requests.pop(true)
151
-
152
- expect(proxied_request.header['proxy-authorization'].first)
153
- .to eq('Basic dXNlcjpwYXNzd29yZA==')
154
-
155
- # rubocop:disable Layout/LineLength
156
- expect(proxied_request.request_line)
157
- .to eq("POST http://localhost:#{proxy.config[:Port]}/api/v3/projects/105138/notices HTTP/1.1\r\n")
158
- # rubocop:enable Layout/LineLength
159
- end
160
- end
161
- # rubocop:enable RSpec/MultipleMemoizedHelpers
162
-
163
- describe ":environment" do
164
- context "when present" do
165
- before { Airbrake::Config.instance.merge(environment: :production) }
166
-
167
- it "being included into the notice's payload" do
168
- notice_notifier.notify_sync(ex)
169
- expect(
170
- a_request(:post, endpoint)
171
- .with(body: /"context":{.*"environment":"production".*}/),
172
- ).to have_been_made.once
173
- end
174
- end
175
- end
176
-
177
- describe ":ignore_environments" do
178
- shared_examples 'sent notice' do |params|
179
- before { Airbrake::Config.instance.merge(params) }
180
-
181
- it "sends a notice" do
182
- notice_notifier.notify_sync(ex)
183
- expect(a_request(:post, endpoint)).to have_been_made
184
- end
185
- end
186
-
187
- shared_examples 'ignored notice' do |params|
188
- before { Airbrake::Config.instance.merge(params) }
189
-
190
- it "ignores exceptions occurring in envs that were not configured" do
191
- notice_notifier.notify_sync(ex)
192
- expect(a_request(:post, endpoint)).not_to have_been_made
193
- end
194
- end
195
-
196
- context "when env is set and ignore_environments doesn't mention it" do
197
- params = {
198
- environment: :development,
199
- ignore_environments: [:production],
200
- }
201
-
202
- include_examples 'sent notice', params
203
- end
204
-
205
- context "when the current env and notify envs are the same" do
206
- params = {
207
- environment: :development,
208
- ignore_environments: %i[production development],
209
- }
210
-
211
- include_examples 'ignored notice', params
212
-
213
- it "returns early and doesn't try to parse the given exception" do
214
- allow(Airbrake::Notice).to receive(:new)
215
-
216
- expect(notice_notifier.notify_sync(ex))
217
- .to eq('error' => "current environment 'development' is ignored")
218
-
219
- expect(Airbrake::Notice).not_to have_received(:new)
220
- end
221
-
222
- it "doesn't make an HTTP request" do
223
- expect(a_request(:post, endpoint)).not_to have_been_made
224
- end
225
- end
226
-
227
- context "when the current env is not set and notify envs are present" do
228
- params = { ignore_environments: %i[production development] }
229
-
230
- include_examples 'sent notice', params
231
- end
232
-
233
- context "when the current env is set and notify envs aren't" do
234
- include_examples 'sent notice', environment: :development
235
- end
236
-
237
- context "when ignore_environments specifies a Regexp pattern" do
238
- params = {
239
- environment: :testing,
240
- ignore_environments: ['staging', /test.+/],
241
- }
242
-
243
- include_examples 'ignored notice', params
244
- end
245
- end
246
-
247
- describe ":blocklist_keys" do
248
- # Fixes https://github.com/airbrake/airbrake-ruby/issues/276
249
- context "when specified along with :allowlist_keys" do
250
- context "and when context payload is present" do
251
- before do
252
- Airbrake::Config.instance.merge(
253
- blocklist_keys: %i[password password_confirmation],
254
- allowlist_keys: [:email, /user/i, 'account_id'],
255
- )
256
- end
257
-
258
- it "sends a notice" do
259
- notice = notice_notifier.build_notice(ex)
260
- notice[:context][:headers] = 'banana'
261
- notice_notifier.notify_sync(notice)
262
-
263
- expect(a_request(:post, endpoint)).to have_been_made
264
- end
265
- end
266
- end
267
- end
268
- end
269
- end