exception_notification 4.4.3 → 4.6.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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +1 -1
  3. data/CHANGELOG.rdoc +13 -0
  4. data/Gemfile.lock +352 -0
  5. data/README.md +99 -46
  6. data/docs/notifiers/slack.md +0 -7
  7. data/exception_notification.gemspec +7 -7
  8. data/gemfiles/{rails5_0.gemfile → rails6_1.gemfile} +1 -1
  9. data/gemfiles/{rails4_2.gemfile → rails7_0.gemfile} +1 -1
  10. data/lib/exception_notification/rails/runner_tie.rb +31 -0
  11. data/lib/exception_notification/rails.rb +16 -0
  12. data/lib/exception_notification/rake.rb +60 -0
  13. data/lib/exception_notification/version.rb +1 -1
  14. data/lib/exception_notifier/email_notifier.rb +1 -1
  15. data/lib/exception_notifier/modules/error_grouping.rb +1 -0
  16. data/lib/exception_notifier/modules/formatter.rb +5 -1
  17. data/lib/exception_notifier/slack_notifier.rb +3 -0
  18. data/lib/exception_notifier/sns_notifier.rb +3 -0
  19. data/lib/exception_notifier/teams_notifier.rb +9 -6
  20. data/lib/exception_notifier/views/exception_notifier/_data.html.erb +1 -1
  21. data/lib/exception_notifier/views/exception_notifier/_data.text.erb +1 -1
  22. data/lib/exception_notifier/views/exception_notifier/_session.html.erb +1 -1
  23. data/lib/exception_notifier/views/exception_notifier/_session.text.erb +1 -1
  24. data/lib/exception_notifier.rb +0 -1
  25. data/lib/generators/exception_notification/install_generator.rb +1 -1
  26. data/lib/generators/exception_notification/templates/exception_notification.rb.erb +3 -1
  27. data/test/exception_notification/rake_test.rb +38 -0
  28. data/test/exception_notifier/email_notifier_test.rb +8 -12
  29. data/test/exception_notifier/hipchat_notifier_test.rb +1 -7
  30. data/test/exception_notifier/sidekiq_test.rb +5 -1
  31. data/test/exception_notifier/sns_notifier_test.rb +55 -0
  32. metadata +46 -53
  33. data/examples/sample_app.rb +0 -56
  34. data/examples/sinatra/Gemfile +0 -10
  35. data/examples/sinatra/Gemfile.lock +0 -95
  36. data/examples/sinatra/Procfile +0 -2
  37. data/examples/sinatra/README.md +0 -11
  38. data/examples/sinatra/config.ru +0 -5
  39. data/examples/sinatra/sinatra_app.rb +0 -40
  40. data/gemfiles/rails4_0.gemfile +0 -7
  41. data/gemfiles/rails4_1.gemfile +0 -7
  42. data/gemfiles/rails5_1.gemfile +0 -7
  43. data/lib/exception_notifier/campfire_notifier.rb +0 -41
  44. data/test/exception_notifier/campfire_notifier_test.rb +0 -127
@@ -6,22 +6,22 @@ Gem::Specification.new do |s|
6
6
  s.name = 'exception_notification'
7
7
  s.version = ExceptionNotification::VERSION
8
8
  s.authors = ['Jamis Buck', 'Josh Peek']
9
- s.date = '2020-06-29'
10
9
  s.summary = 'Exception notification for Rails apps'
11
10
  s.homepage = 'https://smartinez87.github.io/exception_notification/'
12
11
  s.email = 'smartinez87@gmail.com'
13
12
  s.license = 'MIT'
13
+ s.metadata = { 'changelog_uri' => 'https://github.com/smartinez87/exception_notification/blob/master/CHANGELOG.rdoc' }
14
14
 
15
15
  s.required_ruby_version = '>= 2.3'
16
16
  s.required_rubygems_version = '>= 1.8.11'
17
17
 
18
- s.files = `git ls-files`.split("\n")
18
+ s.files = `git ls-files | grep -v '^examples'`.split("\n")
19
19
  s.files -= `git ls-files -- .??*`.split("\n")
20
20
  s.test_files = `git ls-files -- test`.split("\n")
21
21
  s.require_path = 'lib'
22
22
 
23
- s.add_dependency('actionmailer', '>= 4.0', '< 7')
24
- s.add_dependency('activesupport', '>= 4.0', '< 7')
23
+ s.add_dependency('actionmailer', '>= 5.2', '< 9')
24
+ s.add_dependency('activesupport', '>= 5.2', '< 9')
25
25
 
26
26
  s.add_development_dependency 'appraisal', '~> 2.2.0'
27
27
  s.add_development_dependency 'aws-sdk-sns', '~> 1'
@@ -32,11 +32,11 @@ Gem::Specification.new do |s|
32
32
  s.add_development_dependency 'httparty', '~> 0.10.2'
33
33
  s.add_development_dependency 'mocha', '>= 0.13.0'
34
34
  s.add_development_dependency 'mock_redis', '~> 0.19.0'
35
- s.add_development_dependency 'rails', '>= 4.0', '< 7'
35
+ s.add_development_dependency 'net-smtp'
36
+ s.add_development_dependency 'rails', '>= 5.2', '< 9'
36
37
  s.add_development_dependency 'resque', '~> 1.8.0'
37
- s.add_development_dependency 'rubocop', '0.78.0'
38
+ s.add_development_dependency 'rubocop'
38
39
  s.add_development_dependency 'sidekiq', '>= 5.0.4'
39
40
  s.add_development_dependency 'slack-notifier', '>= 1.0.0'
40
41
  s.add_development_dependency 'timecop', '~> 0.9.0'
41
- s.add_development_dependency 'tinder', '~> 1.8'
42
42
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "rails", "~> 5.0.0"
5
+ gem "rails", "~> 6.1.0"
6
6
 
7
7
  gemspec path: "../"
@@ -2,6 +2,6 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "rails", "~> 4.2.0"
5
+ gem "rails", "~> 7.0.0"
6
6
 
7
7
  gemspec path: "../"
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ExceptionNotification
4
+ module Rails
5
+ class RunnerTie
6
+ # Registers an at_exit callback, which checks if there was an exception. This is a pretty
7
+ # crude way to detect exceptions from runner commands, but Rails doesn't provide a better API.
8
+ #
9
+ # This should only be called from a runner callback in your Rails config; otherwise you may
10
+ # register the at_exit callback in more places than you need or want it.
11
+ def call
12
+ at_exit do
13
+ exception = $ERROR_INFO
14
+ if exception && !exception.is_a?(SystemExit)
15
+ ExceptionNotifier.notify_exception(exception, data: data_for_exception_notifier(exception))
16
+ end
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def data_for_exception_notifier(exception = nil)
23
+ data = {}
24
+ data[:error_class] = exception.class.name if exception
25
+ data[:error_message] = exception.message if exception
26
+
27
+ data
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,5 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Warning: This must be required after rails but before initializers have been run. If you require
4
+ # it from config/initializers/exception_notification.rb, then the rails and rake_task callbacks
5
+ # registered here will have no effect, because Rails will have already invoked all registered rails
6
+ # and rake_tasks handlers.
7
+
3
8
  module ExceptionNotification
4
9
  class Engine < ::Rails::Engine
5
10
  config.exception_notification = ExceptionNotifier
@@ -7,5 +12,16 @@ module ExceptionNotification
7
12
  config.exception_notification.error_grouping_cache = Rails.cache
8
13
 
9
14
  config.app_middleware.use ExceptionNotification::Rack
15
+
16
+ rake_tasks do
17
+ # Report exceptions occurring in Rake tasks.
18
+ require 'exception_notification/rake'
19
+ end
20
+
21
+ runner do
22
+ # Report exceptions occurring in runner commands.
23
+ require 'exception_notification/rails/runner_tie'
24
+ Rails::RunnerTie.new.call
25
+ end
10
26
  end
11
27
  end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copied/adapted from https://github.com/airbrake/airbrake/blob/master/lib/airbrake/rake.rb
4
+
5
+ Rake::TaskManager.record_task_metadata = true if Rake.const_defined?(:TaskManager)
6
+
7
+ module ExceptionNotification
8
+ module RakeTaskExtensions
9
+ # A wrapper around the original +#execute+, that catches all errors and
10
+ # passes them on to ExceptionNotifier.
11
+ #
12
+ # rubocop:disable Lint/RescueException
13
+ def execute(args = nil)
14
+ super(args)
15
+ rescue Exception => e
16
+ ExceptionNotifier.notify_exception(e, data: data_for_exception_notifier(e)) unless e.is_a?(SystemExit)
17
+ raise e
18
+ end
19
+ # rubocop:enable Lint/RescueException
20
+
21
+ private
22
+
23
+ def data_for_exception_notifier(exception = nil)
24
+ data = {}
25
+ data[:error_class] = exception.class.name if exception
26
+ data[:error_message] = exception.message if exception
27
+
28
+ data[:rake] = {}
29
+ data[:rake][:rake_command_line] = reconstruct_command_line
30
+ data[:rake][:name] = name
31
+ data[:rake][:timestamp] = timestamp.to_s
32
+ # data[:investigation] = investigation
33
+
34
+ data[:rake][:full_comment] = full_comment if full_comment
35
+ data[:rake][:arg_names] = arg_names if arg_names.any?
36
+ data[:rake][:arg_description] = arg_description if arg_description
37
+ data[:rake][:locations] = locations if locations.any?
38
+ data[:rake][:sources] = sources if sources.any?
39
+
40
+ if prerequisite_tasks.any?
41
+ data[:rake][:prerequisite_tasks] = prerequisite_tasks.map do |p|
42
+ p.__send__(:data_for_exception_notifier)[:rake]
43
+ end
44
+ end
45
+
46
+ data
47
+ end
48
+ # rubocop:enable
49
+
50
+ def reconstruct_command_line
51
+ "rake #{ARGV.join(' ')}"
52
+ end
53
+ end
54
+ end
55
+
56
+ module Rake
57
+ class Task
58
+ prepend ExceptionNotification::RakeTaskExtensions
59
+ end
60
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ExceptionNotification
4
- VERSION = '4.4.3'
4
+ VERSION = '4.6.0'
5
5
  end
@@ -76,7 +76,7 @@ module ExceptionNotifier
76
76
  def compose_subject
77
77
  subject = @options[:email_prefix].to_s.dup
78
78
  subject << "(#{@options[:accumulated_errors_count]} times)" if @options[:accumulated_errors_count].to_i > 1
79
- subject << "#{@kontroller.controller_name} #{@kontroller.action_name}" if include_controller?
79
+ subject << "#{@kontroller.controller_name}##{@kontroller.action_name}" if include_controller?
80
80
  subject << " (#{@exception.class})"
81
81
  subject << " #{@exception.message.inspect}" if @options[:verbose_subject]
82
82
  subject = EmailNotifier.normalize_digits(subject) if @options[:normalize_subject]
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'active_support'
3
4
  require 'active_support/core_ext/numeric/time'
4
5
  require 'active_support/concern'
5
6
 
@@ -111,7 +111,11 @@ module ExceptionNotifier
111
111
  def rails_app_name
112
112
  return unless defined?(::Rails) && ::Rails.respond_to?(:application)
113
113
 
114
- Rails.application.class.parent_name.underscore
114
+ if Rails::VERSION::MAJOR >= 6
115
+ Rails.application.class.module_parent_name.underscore
116
+ else
117
+ Rails.application.class.parent_name.underscore
118
+ end
115
119
  end
116
120
 
117
121
  def controller
@@ -72,6 +72,9 @@ module ExceptionNotifier
72
72
  exception_name = "*#{measure_word}* `#{exception_class}`"
73
73
  env = options[:env]
74
74
 
75
+ options[:headers] ||= {}
76
+ options[:headers]['Content-Type'] = 'application/json'
77
+
75
78
  if env.nil?
76
79
  data = options[:data] || {}
77
80
  text = "#{exception_name} *occured in background*\n"
@@ -45,10 +45,12 @@ module ExceptionNotifier
45
45
 
46
46
  if options[:env].nil?
47
47
  text = "#{exception_name} occured in background\n"
48
+ data = options[:data] || {}
48
49
  else
49
50
  env = options[:env]
50
51
 
51
52
  kontroller = env['action_controller.instance']
53
+ data = (env['exception_notifier.exception_data'] || {}).merge(options[:data] || {})
52
54
  request = "#{env['REQUEST_METHOD']} <#{env['REQUEST_URI']}>"
53
55
 
54
56
  text = "#{exception_name} occurred while #{request}"
@@ -57,6 +59,7 @@ module ExceptionNotifier
57
59
 
58
60
  text += "Exception: #{exception.message}\n"
59
61
  text += "Hostname: #{Socket.gethostname}\n"
62
+ text += "Data: #{data}\n"
60
63
 
61
64
  return unless exception.backtrace
62
65
 
@@ -38,7 +38,7 @@ module ExceptionNotifier
38
38
  @controller = @request_items = nil
39
39
  else
40
40
  @controller = @env['action_controller.instance'] || MissingController.new
41
-
41
+ @additional_exception_data = @env['exception_notifier.exception_data']
42
42
  request = ActionDispatch::Request.new(@env)
43
43
 
44
44
  @request_items = { url: request.original_url,
@@ -47,10 +47,6 @@ module ExceptionNotifier
47
47
  parameters: request.filtered_parameters,
48
48
  timestamp: Time.current }
49
49
 
50
- if request.session['warden.user.user.key']
51
- current_user = User.find(request.session['warden.user.user.key'][0][0])
52
- @request_items[:current_user] = { id: current_user.id, email: current_user.email }
53
- end
54
50
  end
55
51
 
56
52
  payload = message_text
@@ -96,7 +92,7 @@ module ExceptionNotifier
96
92
 
97
93
  details['facts'].push message_request unless @request_items.nil?
98
94
  details['facts'].push message_backtrace unless @backtrace.nil?
99
-
95
+ details['facts'].push additional_exception_data unless @additional_exception_data.nil?
100
96
  details
101
97
  end
102
98
 
@@ -127,6 +123,13 @@ module ExceptionNotifier
127
123
  }
128
124
  end
129
125
 
126
+ def additional_exception_data
127
+ {
128
+ 'name' => 'Data',
129
+ 'value' => "`#{@additional_exception_data}`\n "
130
+ }
131
+ end
132
+
130
133
  def gitlab_view_link
131
134
  {
132
135
  '@type' => 'ViewAction',
@@ -1,6 +1,6 @@
1
1
  <ul style="list-style: none">
2
2
  <li>
3
3
  <strong>data:</strong>
4
- <span><%= PP.pp(@data, "") %></span>
4
+ <span><%= PP.pp(@data, +"") %></span>
5
5
  </li>
6
6
  </ul>
@@ -1 +1 @@
1
- * data: <%= raw PP.pp(@data, "") %>
1
+ * data: <%= raw PP.pp(@data, +"") %>
@@ -5,6 +5,6 @@
5
5
  </li>
6
6
  <li>
7
7
  <strong>data: </strong>
8
- <span><%= PP.pp(@request.session.to_hash, "") %></span>
8
+ <span><%= PP.pp(@request.session.to_hash, +"") %></span>
9
9
  </li>
10
10
  </ul>
@@ -1,2 +1,2 @@
1
1
  * session id: <%= @request.ssl? ? "[FILTERED]" : (raw (@request.session['session_id'] || (@request.env["rack.session.options"] and @request.env["rack.session.options"][:id])).inspect.html_safe) %>
2
- * data: <%= raw PP.pp(@request.session.to_hash, "") %>
2
+ * data: <%= raw PP.pp(@request.session.to_hash, +"") %>
@@ -14,7 +14,6 @@ module ExceptionNotifier
14
14
 
15
15
  autoload :Notifier, 'exception_notifier/notifier'
16
16
  autoload :EmailNotifier, 'exception_notifier/email_notifier'
17
- autoload :CampfireNotifier, 'exception_notifier/campfire_notifier'
18
17
  autoload :HipchatNotifier, 'exception_notifier/hipchat_notifier'
19
18
  autoload :WebhookNotifier, 'exception_notifier/webhook_notifier'
20
19
  autoload :IrcNotifier, 'exception_notifier/irc_notifier'
@@ -2,7 +2,7 @@
2
2
 
3
3
  module ExceptionNotification
4
4
  module Generators
5
- class InstallGenerator < Rails::Generators::Base
5
+ class InstallGenerator < ::Rails::Generators::Base
6
6
  desc 'Creates a ExceptionNotification initializer.'
7
7
 
8
8
  source_root File.expand_path('templates', __dir__)
@@ -1,4 +1,6 @@
1
+ # Move this require to your `config/application.rb` if you want to be notified from runner commands too.
1
2
  require 'exception_notification/rails'
3
+ require 'exception_notification/rake'
2
4
  <% if options.sidekiq? %>
3
5
  require 'exception_notification/sidekiq'
4
6
  <% end %>
@@ -19,7 +21,7 @@ ExceptionNotification.configure do |config|
19
21
  # Adds a condition to decide when an exception must be ignored or not.
20
22
  # The ignore_if method can be invoked multiple times to add extra conditions.
21
23
  # config.ignore_if do |exception, options|
22
- # not Rails.env.production?
24
+ # Rails.env.local?
23
25
  # end
24
26
 
25
27
  # Ignore exceptions generated by crawlers
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ require 'rake'
6
+ require 'exception_notification/rake'
7
+
8
+ class RakeTest < ActiveSupport::TestCase
9
+ setup do
10
+ Rake::Task.define_task :dependency_1 do
11
+ puts :dependency_1
12
+ end
13
+ Rake::Task.define_task raise_exception: :dependency_1 do
14
+ raise 'test exception'
15
+ end
16
+ @task = Rake::Task[:raise_exception]
17
+ end
18
+
19
+ test 'notifies of exception' do
20
+ ExceptionNotifier.expects(:notify_exception).with do |ex, opts|
21
+ data = opts[:data]
22
+ ex.is_a?(RuntimeError) &&
23
+ ex.message == 'test exception' &&
24
+ data[:error_class] == 'RuntimeError' &&
25
+ data[:error_message] == 'test exception' &&
26
+ data[:rake][:rake_command_line] == 'rake ' &&
27
+ data[:rake][:name] == 'raise_exception' &&
28
+ data[:rake][:timestamp] &&
29
+ data[:rake][:sources] == ['dependency_1'] &&
30
+ data[:rake][:prerequisite_tasks][0][:name] == 'dependency_1'
31
+ end
32
+
33
+ # The original error is re-raised
34
+ assert_raises(RuntimeError) do
35
+ @task.invoke
36
+ end
37
+ end
38
+ end
@@ -239,6 +239,7 @@ class EmailNotifierWithEnvTest < ActiveSupport::TestCase
239
239
  'action_dispatch.parameter_filter' => ['secret'],
240
240
  'HTTPS' => 'on',
241
241
  'action_controller.instance' => @controller,
242
+ 'rack.session.options' => {},
242
243
  params: { id: 'foo', secret: 'secret' }
243
244
  )
244
245
 
@@ -248,7 +249,7 @@ class EmailNotifierWithEnvTest < ActiveSupport::TestCase
248
249
  test 'sends mail with correct content' do
249
250
  assert_equal %("Dummy Notifier" <dummynotifier@example.com>), @mail[:from].value
250
251
  assert_equal %w[dummyexceptions@example.com], @mail.to
251
- assert_equal '[Dummy ERROR] home index (ZeroDivisionError) "divided by 0"', @mail.subject
252
+ assert_equal '[Dummy ERROR] home#index (ZeroDivisionError) "divided by 0"', @mail.subject
252
253
  assert_equal 'foobar', @mail['X-Custom-Header'].value
253
254
  assert_equal 'text/plain; charset=UTF-8', @mail.content_type
254
255
  assert_equal [], @mail.attachments
@@ -294,8 +295,7 @@ class EmailNotifierWithEnvTest < ActiveSupport::TestCase
294
295
  Environment:
295
296
  -------------------------------
296
297
 
297
- * CONTENT_LENGTH : 0
298
- * HTTPS : on
298
+ * HTTPS : on
299
299
  * HTTP_HOST : test.address
300
300
  * HTTP_USER_AGENT : Rails Testing
301
301
  * PATH_INFO : /
@@ -305,23 +305,19 @@ class EmailNotifierWithEnvTest < ActiveSupport::TestCase
305
305
  * SCRIPT_NAME :
306
306
  * SERVER_NAME : example.org
307
307
  * SERVER_PORT : 80
308
+ * SERVER_PROTOCOL : HTTP/1.1
308
309
  * action_controller.instance : #{@controller}
309
310
  * action_dispatch.parameter_filter : [\"secret\"]
310
- * action_dispatch.request.content_type :
311
311
  * action_dispatch.request.parameters : {"id"=>"foo", "secret"=>"[FILTERED]"}
312
312
  * action_dispatch.request.path_parameters : {}
313
313
  * action_dispatch.request.query_parameters : {"id"=>"foo", "secret"=>"[FILTERED]"}
314
314
  * action_dispatch.request.request_parameters: {}
315
315
  * rack.errors : #{@test_env['rack.errors']}
316
- * rack.input : #{@test_env['rack.input']}
317
- * rack.multiprocess : true
318
- * rack.multithread : true
319
- * rack.request.query_hash : {"id"=>"foo", "secret"=>"[FILTERED]"}
320
- * rack.request.query_string : id=foo&secret=secret
321
- * rack.run_once : false
322
- * rack.session : {}
316
+ * rack.request.form_hash : {}
317
+ * rack.request.form_input :
318
+ * rack.session : #{@test_env['rack.session']}
319
+ * rack.session.options : #{@test_env['rack.session.options']}
323
320
  * rack.url_scheme : http
324
- * rack.version : #{Rack::VERSION}
325
321
 
326
322
  -------------------------------
327
323
  Backtrace:
@@ -2,13 +2,7 @@
2
2
 
3
3
  require 'test_helper'
4
4
  require 'rack'
5
-
6
- # silence_warnings trick around require can be removed once
7
- # https://github.com/hipchat/hipchat-rb/pull/174
8
- # gets merged and released
9
- silence_warnings do
10
- require 'hipchat'
11
- end
5
+ require 'hipchat'
12
6
 
13
7
  class HipchatNotifierTest < ActiveSupport::TestCase
14
8
  test 'should send hipchat notification if properly configured' do
@@ -11,7 +11,11 @@ require 'sidekiq/testing'
11
11
  require 'exception_notification/sidekiq'
12
12
 
13
13
  class MockSidekiqServer
14
- include ::Sidekiq::ExceptionHandler
14
+ include ::Sidekiq::Component
15
+
16
+ def config
17
+ Sidekiq.default_configuration
18
+ end
15
19
  end
16
20
 
17
21
  class SidekiqTest < ActiveSupport::TestCase
@@ -66,6 +66,7 @@ class SnsNotifierTest < ActiveSupport::TestCase
66
66
  message: "3 MyException occured in background\n" \
67
67
  "Exception: undefined method 'method=' for Empty\n" \
68
68
  "Hostname: example.com\n" \
69
+ "Data: {}\n" \
69
70
  "Backtrace:\n#{fake_backtrace.join("\n")}\n",
70
71
  subject: '[App Exception] - 3 MyException occurred'
71
72
  )
@@ -85,6 +86,7 @@ class SnsNotifierTest < ActiveSupport::TestCase
85
86
  "was processed by examples#index\n" \
86
87
  "Exception: undefined method 'method=' for Empty\n" \
87
88
  "Hostname: example.com\n" \
89
+ "Data: {}\n" \
88
90
  "Backtrace:\n#{fake_backtrace.join("\n")}\n",
89
91
  subject: '[App Exception] - A MyException occurred'
90
92
  )
@@ -98,6 +100,59 @@ class SnsNotifierTest < ActiveSupport::TestCase
98
100
  })
99
101
  end
100
102
 
103
+ test 'should put data from env["exception_notifier.exception_data"] into text' do
104
+ controller = mock('controller')
105
+ controller.stubs(:action_name).returns('index')
106
+ controller.stubs(:controller_name).returns('examples')
107
+
108
+ Aws::SNS::Client.any_instance.expects(:publish).with(
109
+ topic_arn: 'topicARN',
110
+ message: 'A MyException occurred while GET </examples> ' \
111
+ "was processed by examples#index\n" \
112
+ "Exception: undefined method 'method=' for Empty\n" \
113
+ "Hostname: example.com\n" \
114
+ "Data: {:current_user=>12}\n" \
115
+ "Backtrace:\n#{fake_backtrace.join("\n")}\n",
116
+ subject: '[App Exception] - A MyException occurred'
117
+ )
118
+
119
+ sns_notifier = ExceptionNotifier::SnsNotifier.new(@options)
120
+ sns_notifier.call(@exception,
121
+ env: {
122
+ 'REQUEST_METHOD' => 'GET',
123
+ 'REQUEST_URI' => '/examples',
124
+ 'action_controller.instance' => controller,
125
+ 'exception_notifier.exception_data' => { current_user: 12 }
126
+ })
127
+ end
128
+ test 'should put optional data into text' do
129
+ controller = mock('controller')
130
+ controller.stubs(:action_name).returns('index')
131
+ controller.stubs(:controller_name).returns('examples')
132
+
133
+ Aws::SNS::Client.any_instance.expects(:publish).with(
134
+ topic_arn: 'topicARN',
135
+ message: 'A MyException occurred while GET </examples> ' \
136
+ "was processed by examples#index\n" \
137
+ "Exception: undefined method 'method=' for Empty\n" \
138
+ "Hostname: example.com\n" \
139
+ "Data: {:current_user=>12}\n" \
140
+ "Backtrace:\n#{fake_backtrace.join("\n")}\n",
141
+ subject: '[App Exception] - A MyException occurred'
142
+ )
143
+
144
+ sns_notifier = ExceptionNotifier::SnsNotifier.new(@options)
145
+ sns_notifier.call(@exception,
146
+ env: {
147
+ 'REQUEST_METHOD' => 'GET',
148
+ 'REQUEST_URI' => '/examples',
149
+ 'action_controller.instance' => controller
150
+ },
151
+ data: {
152
+ current_user: 12
153
+ })
154
+ end
155
+
101
156
  private
102
157
 
103
158
  def fake_exception