exception_notification 5.0.0 → 5.0.1

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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.rdoc +14 -0
  3. data/exception_notification.gemspec +9 -2
  4. data/lib/exception_notification/version.rb +1 -1
  5. metadata +2 -31
  6. data/Gemfile +0 -5
  7. data/Gemfile.lock +0 -346
  8. data/gemfiles/pinned_dependencies.gemfile +0 -8
  9. data/gemfiles/rails7_1.gemfile +0 -5
  10. data/gemfiles/rails7_2.gemfile +0 -5
  11. data/gemfiles/rails8_0.gemfile +0 -5
  12. data/test/exception_notification/rack_test.rb +0 -106
  13. data/test/exception_notification/rake_test.rb +0 -38
  14. data/test/exception_notification/resque_test.rb +0 -54
  15. data/test/exception_notifier/datadog_notifier_test.rb +0 -154
  16. data/test/exception_notifier/email_notifier_test.rb +0 -342
  17. data/test/exception_notifier/google_chat_notifier_test.rb +0 -185
  18. data/test/exception_notifier/hipchat_notifier_test.rb +0 -220
  19. data/test/exception_notifier/irc_notifier_test.rb +0 -139
  20. data/test/exception_notifier/mattermost_notifier_test.rb +0 -251
  21. data/test/exception_notifier/modules/error_grouping_test.rb +0 -167
  22. data/test/exception_notifier/modules/formatter_test.rb +0 -154
  23. data/test/exception_notifier/sidekiq_test.rb +0 -41
  24. data/test/exception_notifier/slack_notifier_test.rb +0 -228
  25. data/test/exception_notifier/sns_notifier_test.rb +0 -181
  26. data/test/exception_notifier/teams_notifier_test.rb +0 -92
  27. data/test/exception_notifier/webhook_notifier_test.rb +0 -98
  28. data/test/exception_notifier_test.rb +0 -298
  29. data/test/support/exception_notifier_helper.rb +0 -14
  30. data/test/support/views/exception_notifier/_new_bkg_section.html.erb +0 -1
  31. data/test/support/views/exception_notifier/_new_bkg_section.text.erb +0 -1
  32. data/test/support/views/exception_notifier/_new_section.html.erb +0 -1
  33. data/test/support/views/exception_notifier/_new_section.text.erb +0 -1
  34. data/test/test_helper.rb +0 -16
@@ -1,54 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "test_helper"
4
-
5
- require "exception_notification/resque"
6
- require "resque"
7
- require "mock_redis"
8
- require "resque/failure/multiple"
9
- require "resque/failure/redis"
10
-
11
- class ResqueTest < ActiveSupport::TestCase
12
- setup do
13
- # Resque.redis=() only supports a String or Redis instance in Resque 1.8
14
- Resque.instance_variable_set(:@redis, MockRedis.new)
15
-
16
- Resque::Failure::Multiple.classes = [Resque::Failure::Redis, ExceptionNotification::Resque]
17
- Resque::Failure.backend = Resque::Failure::Multiple
18
-
19
- @worker = Resque::Worker.new(:jobs)
20
- # Forking causes issues with Mocha's `.expects`
21
- @worker.cant_fork = true
22
- end
23
-
24
- test "count returns the number of failures" do
25
- Resque::Job.create(:jobs, BadJob)
26
- @worker.work(0)
27
- assert_equal 1, ExceptionNotification::Resque.count
28
- end
29
-
30
- test "notifies exception when job fails" do
31
- ExceptionNotifier.expects(:notify_exception).with do |ex, opts|
32
- ex.is_a?(RuntimeError) &&
33
- ex.message == "Bad job!" &&
34
- opts[:data][:resque][:error_class] == "RuntimeError" &&
35
- opts[:data][:resque][:error_message] == "Bad job!" &&
36
- opts[:data][:resque][:failed_at].present? &&
37
- opts[:data][:resque][:payload] == {
38
- "class" => "ResqueTest::BadJob",
39
- "args" => []
40
- } &&
41
- opts[:data][:resque][:queue] == :jobs &&
42
- opts[:data][:resque][:worker].present?
43
- end
44
-
45
- Resque::Job.create(:jobs, BadJob)
46
- @worker.work(0)
47
- end
48
-
49
- class BadJob
50
- def self.perform
51
- raise "Bad job!"
52
- end
53
- end
54
- end
@@ -1,154 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "test_helper"
4
- require "dogapi/common"
5
- require "dogapi/event"
6
-
7
- class DatadogNotifierTest < ActiveSupport::TestCase
8
- def setup
9
- @client = FakeDatadogClient.new
10
- @options = {
11
- client: @client
12
- }
13
- @notifier = ExceptionNotifier::DatadogNotifier.new(@options)
14
- @exception = FakeException.new
15
- @controller = FakeController.new
16
- @request = FakeRequest.new
17
- end
18
-
19
- test "should send an event to datadog" do
20
- fake_event = Dogapi::Event.any_instance
21
- @client.expects(:emit_event).with(fake_event)
22
-
23
- @notifier.stubs(:datadog_event).returns(fake_event)
24
- @notifier.call(@exception)
25
- end
26
-
27
- test "should include exception class in event title" do
28
- event = @notifier.datadog_event(@exception)
29
- assert_includes event.msg_title, "FakeException"
30
- end
31
-
32
- test "should include prefix in event title and not append previous events" do
33
- options = {
34
- client: @client,
35
- title_prefix: "prefix"
36
- }
37
-
38
- notifier = ExceptionNotifier::DatadogNotifier.new(options)
39
- event = notifier.datadog_event(@exception)
40
- assert_equal event.msg_title, 'prefix (DatadogNotifierTest::FakeException) "Fake exception message"'
41
-
42
- event2 = notifier.datadog_event(@exception)
43
- assert_equal event2.msg_title, 'prefix (DatadogNotifierTest::FakeException) "Fake exception message"'
44
- end
45
-
46
- test "should include exception message in event title" do
47
- event = @notifier.datadog_event(@exception)
48
- assert_includes event.msg_title, "Fake exception message"
49
- end
50
-
51
- test "should include controller info in event title if controller information is available" do
52
- event = @notifier.datadog_event(@exception,
53
- env: {
54
- "action_controller.instance" => @controller,
55
- "REQUEST_METHOD" => "GET",
56
- "rack.input" => ""
57
- })
58
- assert_includes event.msg_title, "Fake controller"
59
- assert_includes event.msg_title, "Fake action"
60
- end
61
-
62
- test "should include backtrace info in event body" do
63
- event = @notifier.datadog_event(@exception)
64
- assert_includes event.msg_text, "backtrace line 1\nbacktrace line 2\nbacktrace line 3"
65
- end
66
-
67
- test "should include request info in event body" do
68
- ActionDispatch::Request.stubs(:new).returns(@request)
69
-
70
- event = @notifier.datadog_event(@exception,
71
- env: {
72
- "action_controller.instance" => @controller,
73
- "REQUEST_METHOD" => "GET",
74
- "rack.input" => ""
75
- })
76
- assert_includes event.msg_text, "http://localhost:8080"
77
- assert_includes event.msg_text, "GET"
78
- assert_includes event.msg_text, "127.0.0.1"
79
- assert_includes event.msg_text, {"param 1" => "value 1", "param 2" => "value 2"}.to_s
80
- end
81
-
82
- test "should include tags in event" do
83
- options = {
84
- client: @client,
85
- tags: %w[error production]
86
- }
87
- notifier = ExceptionNotifier::DatadogNotifier.new(options)
88
- event = notifier.datadog_event(@exception)
89
- assert_equal event.tags, %w[error production]
90
- end
91
-
92
- test "should include event title in event aggregation key" do
93
- event = @notifier.datadog_event(@exception)
94
- assert_equal event.aggregation_key, [event.msg_title]
95
- end
96
-
97
- class FakeDatadogClient
98
- def emit_event(event)
99
- end
100
- end
101
-
102
- class FakeController
103
- def controller_name
104
- "Fake controller"
105
- end
106
-
107
- def action_name
108
- "Fake action"
109
- end
110
- end
111
-
112
- class FakeException
113
- def backtrace
114
- [
115
- "backtrace line 1",
116
- "backtrace line 2",
117
- "backtrace line 3",
118
- "backtrace line 4",
119
- "backtrace line 5"
120
- ]
121
- end
122
-
123
- def message
124
- "Fake exception message"
125
- end
126
- end
127
-
128
- class FakeRequest
129
- def url
130
- "http://localhost:8080"
131
- end
132
-
133
- def request_method
134
- "GET"
135
- end
136
-
137
- def remote_ip
138
- "127.0.0.1"
139
- end
140
-
141
- def filtered_parameters
142
- {
143
- "param 1" => "value 1",
144
- "param 2" => "value 2"
145
- }
146
- end
147
-
148
- def session
149
- {
150
- "session_id" => "1234"
151
- }
152
- end
153
- end
154
- end
@@ -1,342 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "test_helper"
4
- require "action_mailer"
5
- require "action_controller"
6
-
7
- class EmailNotifierTest < ActiveSupport::TestCase
8
- setup do
9
- Time.stubs(:current).returns("Sat, 20 Apr 2013 20:58:55 UTC +00:00")
10
-
11
- @exception = ZeroDivisionError.new("divided by 0")
12
- @exception.set_backtrace(["test/exception_notifier/email_notifier_test.rb:20"])
13
-
14
- @email_notifier = ExceptionNotifier::EmailNotifier.new(
15
- email_prefix: "[Dummy ERROR] ",
16
- sender_address: %("Dummy Notifier" <dummynotifier@example.com>),
17
- exception_recipients: %w[dummyexceptions@example.com],
18
- email_headers: {"X-Custom-Header" => "foobar"},
19
- sections: %w[new_section request session environment backtrace],
20
- background_sections: %w[new_bkg_section backtrace data],
21
- pre_callback: proc { |_opts, _notifier, _backtrace, _message, _message_opts| @pre_callback_called = true },
22
- post_callback: proc { |_opts, _notifier, _backtrace, _message, _message_opts| @post_callback_called = true },
23
- smtp_settings: {
24
- user_name: "Dummy user_name",
25
- password: "Dummy password"
26
- }
27
- )
28
-
29
- @mail = @email_notifier.call(
30
- @exception,
31
- data: {job: "DivideWorkerJob", payload: "1/0", message: "My Custom Message"}
32
- )
33
- end
34
-
35
- test "should call pre/post_callback if specified" do
36
- assert @pre_callback_called
37
- assert @post_callback_called
38
- end
39
-
40
- test "sends mail with correct content" do
41
- assert_equal %("Dummy Notifier" <dummynotifier@example.com>), @mail[:from].value
42
- assert_equal %w[dummyexceptions@example.com], @mail.to
43
- assert_equal '[Dummy ERROR] (ZeroDivisionError) "divided by 0"', @mail.subject
44
- assert_equal "foobar", @mail["X-Custom-Header"].value
45
- assert_equal "text/plain; charset=UTF-8", @mail.content_type
46
- assert_equal [], @mail.attachments
47
- assert_equal "Dummy user_name", @mail.delivery_method.settings[:user_name]
48
- assert_equal "Dummy password", @mail.delivery_method.settings[:password]
49
-
50
- # standard:disable Lint/LiteralInInterpolation
51
- body = <<~BODY
52
- A ZeroDivisionError occurred in background at Sat, 20 Apr 2013 20:58:55 UTC +00:00 :
53
-
54
- divided by 0
55
- test/exception_notifier/email_notifier_test.rb:20
56
-
57
- -------------------------------
58
- New bkg section:
59
- -------------------------------
60
-
61
- * New background section for testing
62
-
63
- -------------------------------
64
- Backtrace:
65
- -------------------------------
66
-
67
- test/exception_notifier/email_notifier_test.rb:20
68
-
69
- -------------------------------
70
- Data:
71
- -------------------------------
72
-
73
- * data: #{{job: "DivideWorkerJob", payload: "1/0", message: "My Custom Message"}}
74
-
75
-
76
- BODY
77
- # standard:enable Lint/LiteralInInterpolation
78
-
79
- assert_equal body, @mail.decode_body
80
- end
81
-
82
- test "should normalize multiple digits into one N" do
83
- assert_equal "N foo N bar N baz N",
84
- ExceptionNotifier::EmailNotifier.normalize_digits("1 foo 12 bar 123 baz 1234")
85
- end
86
-
87
- test "mail should prefix exception class with 'an' instead of 'a' when it starts with a vowel" do
88
- begin
89
- raise ArgumentError
90
- rescue => e
91
- @vowel_exception = e
92
- @vowel_mail = @email_notifier.call(@vowel_exception)
93
- end
94
-
95
- assert_includes @vowel_mail.encoded, "An ArgumentError occurred in background at #{Time.current}"
96
- end
97
-
98
- test "should not send notification if one of ignored exceptions" do
99
- begin
100
- raise AbstractController::ActionNotFound
101
- rescue => e
102
- @ignored_exception = e
103
- unless ExceptionNotifier.ignored_exceptions.include?(@ignored_exception.class.name)
104
- ignored_mail = @email_notifier.call(@ignored_exception)
105
- end
106
- end
107
-
108
- assert_equal @ignored_exception.class.inspect, "AbstractController::ActionNotFound"
109
- assert_nil ignored_mail
110
- end
111
-
112
- test "should encode environment strings" do
113
- email_notifier = ExceptionNotifier::EmailNotifier.new(
114
- sender_address: "<dummynotifier@example.com>",
115
- exception_recipients: %w[dummyexceptions@example.com]
116
- )
117
-
118
- mail = email_notifier.call(
119
- @exception,
120
- env: {
121
- "REQUEST_METHOD" => "GET",
122
- "rack.input" => "",
123
- "invalid_encoding" => "R\xC3\xA9sum\xC3\xA9".dup.force_encoding(Encoding::ASCII)
124
- }
125
- )
126
-
127
- assert_match(/invalid_encoding\s+: R__sum__/, mail.encoded)
128
- end
129
-
130
- test "should send email using ActionMailer" do
131
- ActionMailer::Base.deliveries.clear
132
- @email_notifier.call(@exception)
133
- assert_equal 1, ActionMailer::Base.deliveries.count
134
- end
135
-
136
- test "should be able to specify ActionMailer::MessageDelivery method" do
137
- ActionMailer::Base.deliveries.clear
138
-
139
- deliver_with = if ActionMailer.version < Gem::Version.new("4.2")
140
- :deliver
141
- else
142
- :deliver_now
143
- end
144
-
145
- email_notifier = ExceptionNotifier::EmailNotifier.new(
146
- email_prefix: "[Dummy ERROR] ",
147
- sender_address: %("Dummy Notifier" <dummynotifier@example.com>),
148
- exception_recipients: %w[dummyexceptions@example.com],
149
- deliver_with: deliver_with
150
- )
151
-
152
- email_notifier.call(@exception)
153
-
154
- assert_equal 1, ActionMailer::Base.deliveries.count
155
- end
156
-
157
- test "should lazily evaluate exception_recipients" do
158
- exception_recipients = %w[first@example.com second@example.com]
159
- email_notifier = ExceptionNotifier::EmailNotifier.new(
160
- email_prefix: "[Dummy ERROR] ",
161
- sender_address: %("Dummy Notifier" <dummynotifier@example.com>),
162
- exception_recipients: -> { [exception_recipients.shift] },
163
- delivery_method: :test
164
- )
165
-
166
- mail = email_notifier.call(@exception)
167
- assert_equal %w[first@example.com], mail.to
168
- mail = email_notifier.call(@exception)
169
- assert_equal %w[second@example.com], mail.to
170
- end
171
-
172
- test "should prepend accumulated_errors_count in email subject if accumulated_errors_count larger than 1" do
173
- email_notifier = ExceptionNotifier::EmailNotifier.new(
174
- email_prefix: "[Dummy ERROR] ",
175
- sender_address: %("Dummy Notifier" <dummynotifier@example.com>),
176
- exception_recipients: %w[dummyexceptions@example.com],
177
- delivery_method: :test
178
- )
179
-
180
- mail = email_notifier.call(@exception, accumulated_errors_count: 3)
181
- assert mail.subject.start_with?("[Dummy ERROR] (3 times) (ZeroDivisionError)")
182
- end
183
-
184
- test "should not include exception message in subject when verbose_subject: false" do
185
- email_notifier = ExceptionNotifier::EmailNotifier.new(
186
- sender_address: %("Dummy Notifier" <dummynotifier@example.com>),
187
- exception_recipients: %w[dummyexceptions@example.com],
188
- verbose_subject: false
189
- )
190
-
191
- mail = email_notifier.call(@exception)
192
-
193
- assert_equal "[ERROR] (ZeroDivisionError)", mail.subject
194
- end
195
-
196
- test "should send html email when selected html format" do
197
- email_notifier = ExceptionNotifier::EmailNotifier.new(
198
- sender_address: %("Dummy Notifier" <dummynotifier@example.com>),
199
- exception_recipients: %w[dummyexceptions@example.com],
200
- email_format: :html
201
- )
202
-
203
- mail = email_notifier.call(@exception)
204
-
205
- assert mail.multipart?
206
- end
207
- end
208
-
209
- class EmailNotifierWithEnvTest < ActiveSupport::TestCase
210
- class HomeController < ActionController::Metal
211
- def index
212
- end
213
- end
214
-
215
- setup do
216
- Time.stubs(:current).returns("Sat, 20 Apr 2013 20:58:55 UTC +00:00")
217
-
218
- @exception = ZeroDivisionError.new("divided by 0")
219
- @exception.set_backtrace(["test/exception_notifier/email_notifier_test.rb:20"])
220
-
221
- @email_notifier = ExceptionNotifier::EmailNotifier.new(
222
- email_prefix: "[Dummy ERROR] ",
223
- sender_address: %("Dummy Notifier" <dummynotifier@example.com>),
224
- exception_recipients: %w[dummyexceptions@example.com],
225
- email_headers: {"X-Custom-Header" => "foobar"},
226
- sections: %w[new_section request session environment backtrace],
227
- background_sections: %w[new_bkg_section backtrace data],
228
- pre_callback:
229
- proc { |_opts, _notifier, _backtrace, _message, message_opts| message_opts[:pre_callback_called] = 1 },
230
- post_callback:
231
- proc { |_opts, _notifier, _backtrace, _message, message_opts| message_opts[:post_callback_called] = 1 }
232
- )
233
-
234
- @controller = HomeController.new
235
- @controller.process(:index)
236
-
237
- @test_env = Rack::MockRequest.env_for(
238
- "/",
239
- "HTTP_HOST" => "test.address",
240
- "REMOTE_ADDR" => "127.0.0.1",
241
- "HTTP_USER_AGENT" => "Rails Testing",
242
- "action_dispatch.parameter_filter" => ["secret"],
243
- "HTTPS" => "on",
244
- "action_controller.instance" => @controller,
245
- "rack.session.options" => {},
246
- :params => {id: "foo", secret: "secret"}
247
- )
248
-
249
- @mail = @email_notifier.call(@exception, env: @test_env, data: {message: "My Custom Message"})
250
- end
251
-
252
- test "sends mail with correct content" do
253
- assert_equal %("Dummy Notifier" <dummynotifier@example.com>), @mail[:from].value
254
- assert_equal %w[dummyexceptions@example.com], @mail.to
255
- assert_equal '[Dummy ERROR] home#index (ZeroDivisionError) "divided by 0"', @mail.subject
256
- assert_equal "foobar", @mail["X-Custom-Header"].value
257
- assert_equal "text/plain; charset=UTF-8", @mail.content_type
258
- assert_equal [], @mail.attachments
259
-
260
- body_fragments = []
261
-
262
- # standard:disable Lint/LiteralInInterpolation
263
- body_fragments << <<~BODY
264
- A ZeroDivisionError occurred in home#index:
265
-
266
- divided by 0
267
- test/exception_notifier/email_notifier_test.rb:20
268
-
269
-
270
- -------------------------------
271
- New section:
272
- -------------------------------
273
-
274
- * New text section for testing
275
-
276
- -------------------------------
277
- Request:
278
- -------------------------------
279
-
280
- * URL : https://test.address/?id=foo&secret=secret
281
- * HTTP Method: GET
282
- * IP address : 127.0.0.1
283
- * Parameters : #{{"id" => "foo", "secret" => "[FILTERED]"}}
284
- * Timestamp : Sat, 20 Apr 2013 20:58:55 UTC +00:00
285
- * Server : #{Socket.gethostname}
286
- BODY
287
-
288
- body_fragments << " * Rails root : #{Rails.root}\n" if defined?(Rails) && Rails.respond_to?(:root)
289
-
290
- body_fragments << <<~BODY
291
- * Process: #{Process.pid}
292
-
293
- -------------------------------
294
- Session:
295
- -------------------------------
296
-
297
- * session id: [FILTERED]
298
- * data: {}
299
-
300
- -------------------------------
301
- Environment:
302
- -------------------------------
303
-
304
- BODY
305
-
306
- body_fragments << "* action_controller.instance"
307
- body_fragments << "* rack.errors"
308
- body_fragments << "[FILTERED]"
309
-
310
- body_fragments << <<~BODY
311
- -------------------------------
312
- Backtrace:
313
- -------------------------------
314
-
315
- test/exception_notifier/email_notifier_test.rb:20
316
-
317
- -------------------------------
318
- Data:
319
- -------------------------------
320
-
321
- * data: #{{message: "My Custom Message"}}
322
-
323
-
324
- BODY
325
- # standard:enable Lint/LiteralInInterpolation
326
- body_fragments.each do |fragment|
327
- assert_includes @mail.decode_body, fragment
328
- end
329
- end
330
-
331
- test "should not include controller and action names in subject" do
332
- email_notifier = ExceptionNotifier::EmailNotifier.new(
333
- sender_address: %("Dummy Notifier" <dummynotifier@example.com>),
334
- exception_recipients: %w[dummyexceptions@example.com],
335
- include_controller_and_action_names_in_subject: false
336
- )
337
-
338
- mail = email_notifier.call(@exception, env: @test_env)
339
-
340
- assert_equal "[ERROR] (ZeroDivisionError) \"divided by 0\"", mail.subject
341
- end
342
- end