exception_notification 4.2.0 → 4.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 96b7601841d70bce96aac4688ff838b6547413e3
4
- data.tar.gz: f1d812c03809294aabec50f4c22b5d8d56403bcb
3
+ metadata.gz: 6de21b765af1465df6205f174cbab7e10b403048
4
+ data.tar.gz: cade5525679b528aded7b1ad6369e97f40b58947
5
5
  SHA512:
6
- metadata.gz: 07b9e4c6337d2edde00e095780487a1fe3eda8f391c327d9d2b1ad815aa2a595b9804d0890c1c6338cf015e42b70af1ad8fe7db6ecb1d2769b567af17a7214da
7
- data.tar.gz: e4bf5df059d85c029acb2cac6160218a5e9c822886b17884deed3b1f186b85a40a536b26c516dc546fc4ca1500daf8260e34e7959656c728cf03ad69814f2a7c
6
+ metadata.gz: fe4b7770171a25a7e131d97c922e5c518531f71add293ce42359eb9f2fc84ea7330f2f935657cbf4dc13fa4a8ba2d3d492397469555d665d12d36c52603a82fd
7
+ data.tar.gz: 92774d00ec26d97246ca9d4e6334f3aac06f04c5242a555eb3a5bd5addfd8a8485bdd72787b0d304146c50e79a7ff4500aaf2a08aca744be963f3a779221b193
@@ -1,3 +1,13 @@
1
+ == 4.2.1
2
+
3
+ * enhancements
4
+ * Allow customizable backtrace for Slack (by @aried3r)
5
+ * Add `Mongoid::Errors::DocumentNotFound` to ignored_exceptions (by @nazarok)
6
+ * Improved text in Slack notifier (by @vojtad)
7
+
8
+ * bug fixes
9
+ * Fix data being sent on webhook notifier
10
+
1
11
  == 4.2.0
2
12
 
3
13
  * enhancements
data/README.md CHANGED
@@ -823,7 +823,7 @@ You can choose to ignore certain exceptions, which will make ExceptionNotificati
823
823
 
824
824
  ### :ignore_exceptions
825
825
 
826
- *Array of strings, default: %w{ActiveRecord::RecordNotFound AbstractController::ActionNotFound ActionController::RoutingError ActionController::UnknownFormat}*
826
+ *Array of strings, default: %w{ActiveRecord::RecordNotFound Mongoid::Errors::DocumentNotFound AbstractController::ActionNotFound ActionController::RoutingError ActionController::UnknownFormat}*
827
827
 
828
828
  Ignore specified exception types. To achieve that, you should use the `:ignore_exceptions` option, like this:
829
829
 
@@ -950,21 +950,13 @@ As above, make sure the gem is not listed solely under the `production` group, s
950
950
 
951
951
  ## Versions
952
952
 
953
- For v4.0.1, see this tag:
953
+ For v4.2.1, see this tag:
954
954
 
955
- http://github.com/smartinez87/exception_notification/tree/v4.0.1
955
+ http://github.com/smartinez87/exception_notification/tree/v4.2.1
956
956
 
957
- For v4.0.0, see this tag:
957
+ For v4.2.0, see this tag:
958
958
 
959
- http://github.com/smartinez87/exception_notification/tree/v4.0.0
960
-
961
- For v3.0.1, see this tag:
962
-
963
- http://github.com/smartinez87/exception_notification/tree/v3.0.1
964
-
965
- For v3.0.0, see this tag:
966
-
967
- http://github.com/smartinez87/exception_notification/tree/v3.0.0
959
+ http://github.com/smartinez87/exception_notification/tree/v4.2.0
968
960
 
969
961
  For previous releases, visit:
970
962
 
@@ -1,8 +1,8 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'exception_notification'
3
- s.version = '4.2.0'
3
+ s.version = '4.2.1'
4
4
  s.authors = ["Jamis Buck", "Josh Peek"]
5
- s.date = %q{2016-07-12}
5
+ s.date = %q{2016-07-17}
6
6
  s.summary = "Exception notification for Rails apps"
7
7
  s.homepage = "https://smartinez87.github.io/exception_notification/"
8
8
  s.email = "smartinez87@gmail.com"
@@ -9,22 +9,22 @@ module ExceptionNotification
9
9
 
10
10
  if options.key?(:ignore_if)
11
11
  rack_ignore = options.delete(:ignore_if)
12
- ExceptionNotifier.ignore_if do |exception, options|
13
- options.key?(:env) && rack_ignore.call(options[:env], exception)
12
+ ExceptionNotifier.ignore_if do |exception, opts|
13
+ opts.key?(:env) && rack_ignore.call(opts[:env], exception)
14
14
  end
15
15
  end
16
16
 
17
17
  if options.key?(:ignore_crawlers)
18
18
  ignore_crawlers = options.delete(:ignore_crawlers)
19
- ExceptionNotifier.ignore_if do |exception, options|
20
- options.key?(:env) && from_crawler(options[:env], ignore_crawlers)
19
+ ExceptionNotifier.ignore_if do |exception, opts|
20
+ opts.key?(:env) && from_crawler(opts[:env], ignore_crawlers)
21
21
  end
22
22
  end
23
23
 
24
24
  @ignore_cascade_pass = options.delete(:ignore_cascade_pass) { true }
25
25
 
26
- options.each do |notifier_name, options|
27
- ExceptionNotifier.register_exception_notifier(notifier_name, options)
26
+ options.each do |notifier_name, opts|
27
+ ExceptionNotifier.register_exception_notifier(notifier_name, opts)
28
28
  end
29
29
  end
30
30
 
@@ -24,7 +24,7 @@ module ExceptionNotifier
24
24
 
25
25
  # Define a set of exceptions to be ignored, ie, dont send notifications when any of them are raised.
26
26
  mattr_accessor :ignored_exceptions
27
- @@ignored_exceptions = %w{ActiveRecord::RecordNotFound AbstractController::ActionNotFound ActionController::RoutingError ActionController::UnknownFormat ActionController::UrlGenerationError}
27
+ @@ignored_exceptions = %w{ActiveRecord::RecordNotFound Mongoid::Errors::DocumentNotFound AbstractController::ActionNotFound ActionController::RoutingError ActionController::UnknownFormat ActionController::UrlGenerationError}
28
28
 
29
29
  mattr_accessor :testing_mode
30
30
  @@testing_mode = false
@@ -8,6 +8,7 @@ module ExceptionNotifier
8
8
  super
9
9
  begin
10
10
  @ignore_data_if = options[:ignore_data_if]
11
+ @backtrace_lines = options[:backtrace_lines]
11
12
 
12
13
  webhook_url = options.fetch(:webhook_url)
13
14
  @message_opts = options.fetch(:additional_parameters, {})
@@ -18,10 +19,21 @@ module ExceptionNotifier
18
19
  end
19
20
 
20
21
  def call(exception, options={})
21
- env = options[:env] || {}
22
- title = "#{env['REQUEST_METHOD']} <#{env['REQUEST_URI']}>"
23
- data = (env['exception_notifier.exception_data'] || {}).merge(options[:data] || {})
24
- text = "*An exception occurred while doing*: `#{title}`\n"
22
+ exception_name = "*#{exception.class.to_s =~ /^[aeiou]/i ? 'An' : 'A'}* `#{exception.class.to_s}`"
23
+
24
+ if options[:env].nil?
25
+ data = options[:data] || {}
26
+ text = "#{exception_name} *occured in background*\n"
27
+ else
28
+ env = options[:env]
29
+ data = (env['exception_notifier.exception_data'] || {}).merge(options[:data] || {})
30
+
31
+ kontroller = env['action_controller.instance']
32
+ request = "#{env['REQUEST_METHOD']} <#{env['REQUEST_URI']}>"
33
+ text = "#{exception_name} *occurred while* `#{env['REQUEST_METHOD']} <#{env['REQUEST_URI']}>`"
34
+ text += " *was processed by* `#{kontroller.controller_name}##{kontroller.action_name}`" if kontroller
35
+ text += "\n"
36
+ end
25
37
 
26
38
  clean_message = exception.message.gsub("`", "'")
27
39
  fields = [ { title: 'Exception', value: clean_message} ]
@@ -29,7 +41,7 @@ module ExceptionNotifier
29
41
  fields.push({ title: 'Hostname', value: Socket.gethostname })
30
42
 
31
43
  if exception.backtrace
32
- formatted_backtrace = "```#{exception.backtrace.join("\n")}```"
44
+ formatted_backtrace = @backtrace_lines ? "```#{exception.backtrace.first(@backtrace_lines).join("\n")}```" : "```#{exception.backtrace.join("\n")}```"
33
45
  fields.push({ title: 'Backtrace', value: formatted_backtrace })
34
46
  end
35
47
 
@@ -40,8 +40,8 @@ module ExceptionNotifier
40
40
  options[:body][:session] = request.session
41
41
  options[:body][:environment] = request.filtered_env
42
42
  end
43
- send_notice(exception, options, nil, @default_options) do |msg, opts|
44
- HTTParty.send(http_method, url, opts)
43
+ send_notice(exception, options, nil, @default_options) do |_, _|
44
+ HTTParty.send(http_method, url, options)
45
45
  end
46
46
  end
47
47
  end
@@ -13,7 +13,7 @@ Resque::Failure.backend = Resque::Failure::Multiple
13
13
 
14
14
  ExceptionNotification.configure do |config|
15
15
  # Ignore additional exception types.
16
- # ActiveRecord::RecordNotFound, AbstractController::ActionNotFound and ActionController::RoutingError are already added.
16
+ # ActiveRecord::RecordNotFound, Mongoid::Errors::DocumentNotFound, AbstractController::ActionNotFound and ActionController::RoutingError are already added.
17
17
  # config.ignored_exceptions += %w{ActionView::TemplateError CustomError}
18
18
 
19
19
  # Adds a condition to decide when an exception must be ignored or not.
@@ -3,4 +3,4 @@ require 'rubygems'
3
3
  # Set up gems listed in the Gemfile.
4
4
  ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
5
5
 
6
- require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
6
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
@@ -8,9 +8,6 @@ Dummy::Application.configure do
8
8
  # and recreated between test runs. Don't rely on the data there!
9
9
  config.cache_classes = true
10
10
 
11
- # Log error messages when you accidentally call methods on nil.
12
- config.whiny_nils = true
13
-
14
11
  # Show full error reports and disable caching
15
12
  config.consider_all_requests_local = true
16
13
  config.action_controller.perform_caching = false
@@ -1,5 +1,11 @@
1
1
  require 'test_helper'
2
- require 'tinder'
2
+
3
+ # silence_warnings trick around require can be removed once
4
+ # https://github.com/collectiveidea/tinder/pull/77
5
+ # gets merged and released
6
+ silence_warnings do
7
+ require 'tinder'
8
+ end
3
9
 
4
10
  class CampfireNotifierTest < ActiveSupport::TestCase
5
11
 
@@ -80,7 +86,7 @@ class CampfireNotifierTest < ActiveSupport::TestCase
80
86
  end
81
87
 
82
88
  def fake_exception
83
- exception = begin
89
+ begin
84
90
  5/0
85
91
  rescue Exception => e
86
92
  e
@@ -101,7 +101,7 @@ class EmailNotifierTest < ActiveSupport::TestCase
101
101
  end
102
102
 
103
103
  test "mail should have a descriptive subject" do
104
- assert_match /^\[Dummy ERROR\]\s+\(ZeroDivisionError\) "divided by 0"$/, @mail.subject
104
+ assert_match(/^\[Dummy ERROR\]\s+\(ZeroDivisionError\) "divided by 0"$/, @mail.subject)
105
105
  end
106
106
 
107
107
  test "mail should say exception was raised in background at show timestamp" do
@@ -165,7 +165,7 @@ class EmailNotifierTest < ActiveSupport::TestCase
165
165
  :email_format => :text
166
166
  )
167
167
 
168
- assert_match /invalid_encoding\s+: R__sum__/, mail.encoded
168
+ assert_match(/invalid_encoding\s+: R__sum__/, mail.encoded)
169
169
  end
170
170
 
171
171
  test "should send email using ActionMailer" do
@@ -1,5 +1,11 @@
1
1
  require 'test_helper'
2
- require 'hipchat'
2
+
3
+ # silence_warnings trick around require can be removed once
4
+ # https://github.com/hipchat/hipchat-rb/pull/174
5
+ # gets merged and released
6
+ silence_warnings do
7
+ require 'hipchat'
8
+ end
3
9
 
4
10
  class HipchatNotifierTest < ActiveSupport::TestCase
5
11
 
@@ -152,7 +158,7 @@ class HipchatNotifierTest < ActiveSupport::TestCase
152
158
  end
153
159
 
154
160
  def fake_exception
155
- exception = begin
161
+ begin
156
162
  5/0
157
163
  rescue Exception => e
158
164
  e
@@ -160,7 +166,7 @@ class HipchatNotifierTest < ActiveSupport::TestCase
160
166
  end
161
167
 
162
168
  def fake_exception_with_html_characters
163
- exception = begin
169
+ begin
164
170
  raise StandardError.new('an error with <html> characters')
165
171
  rescue Exception => e
166
172
  e
@@ -108,7 +108,7 @@ class IrcNotifierTest < ActiveSupport::TestCase
108
108
  private
109
109
 
110
110
  def fake_exception
111
- exception = begin
111
+ begin
112
112
  5/0
113
113
  rescue Exception => e
114
114
  e
@@ -12,6 +12,13 @@ class MockSidekiqServer
12
12
  end
13
13
 
14
14
  class SidekiqTest < ActiveSupport::TestCase
15
+ setup do
16
+ @_original_sidekiq_logger = Sidekiq::Logging.logger
17
+
18
+ # Silence sidekiq warning to stdout
19
+ Sidekiq::Logging.logger = nil
20
+ end
21
+
15
22
  test "should call notify_exception when sidekiq raises an error" do
16
23
  server = MockSidekiqServer.new
17
24
  message = Hash.new
@@ -24,4 +31,8 @@ class SidekiqTest < ActiveSupport::TestCase
24
31
 
25
32
  server.handle_exception(exception, message)
26
33
  end
34
+
35
+ teardown do
36
+ Sidekiq::Logging.logger = @_original_sidekiq_logger
37
+ end
27
38
  end
@@ -60,6 +60,18 @@ class SlackNotifierTest < ActiveSupport::TestCase
60
60
  assert_equal slack_notifier.notifier.username, options[:username]
61
61
  end
62
62
 
63
+ test "should send the notification with specific backtrace lines" do
64
+ options = {
65
+ webhook_url: "http://slack.webhook.url",
66
+ backtrace_lines: 1
67
+ }
68
+
69
+ Slack::Notifier.any_instance.expects(:ping).with('', fake_notification(@exception, {}, nil, 1))
70
+
71
+ slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
72
+ slack_notifier.call(@exception)
73
+ end
74
+
63
75
  test "should pass the additional parameters to Slack::Notifier.ping" do
64
76
  options = {
65
77
  webhook_url: "http://slack.webhook.url",
@@ -106,7 +118,7 @@ class SlackNotifierTest < ActiveSupport::TestCase
106
118
 
107
119
  expected_data_string = "foo: bar\njohn: doe\nuser_id: 5"
108
120
 
109
- Slack::Notifier.any_instance.expects(:ping).with('', fake_notification(@exception, expected_data_string))
121
+ Slack::Notifier.any_instance.expects(:ping).with('', fake_notification(@exception, notification_options, expected_data_string))
110
122
  slack_notifier = ExceptionNotifier::SlackNotifier.new(options)
111
123
  slack_notifier.call(@exception, notification_options)
112
124
  end
@@ -165,12 +177,28 @@ class SlackNotifierTest < ActiveSupport::TestCase
165
177
  ]
166
178
  end
167
179
 
168
- def fake_notification(exception = @exception, data_string = nil)
169
- text = "*An exception occurred while doing*: ` <>`\n"
180
+ def fake_notification(exception = @exception, notification_options = {}, data_string = nil, expected_backtrace_lines = nil)
181
+ exception_name = "*#{exception.class.to_s =~ /^[aeiou]/i ? 'An' : 'A'}* `#{exception.class.to_s}`"
182
+ if notification_options[:env].nil?
183
+ text = "#{exception_name} *occured in background*"
184
+ else
185
+ env = notification_options[:env]
186
+
187
+ kontroller = env['action_controller.instance']
188
+ request = "#{env['REQUEST_METHOD']} <#{env['REQUEST_URI']}>"
189
+
190
+ text = "#{exception_name} *occurred while* `#{request}`"
191
+ text += " *was processed by* `#{kontroller.controller_name}##{kontroller.action_name}`" if kontroller
192
+ end
193
+
194
+ text += "\n"
170
195
 
171
196
  fields = [ { title: 'Exception', value: exception.message} ]
172
197
  fields.push({ title: 'Hostname', value: 'example.com' })
173
- fields.push({ title: 'Backtrace', value: "```#{fake_backtrace.join("\n")}```" }) if exception.backtrace
198
+ if exception.backtrace
199
+ formatted_backtrace = expected_backtrace_lines ? "```#{exception.backtrace.first(expected_backtrace_lines).join("\n")}```" : "```#{exception.backtrace.join("\n")}```"
200
+ fields.push({ title: 'Backtrace', value: formatted_backtrace })
201
+ end
174
202
  fields.push({ title: 'Data', value: "```#{data_string}```" }) if data_string
175
203
 
176
204
  { attachments: [ color: 'danger', text: text, fields: fields, mrkdwn_in: %w(text fields) ] }
@@ -14,7 +14,7 @@ class WebhookNotifierTest < ActiveSupport::TestCase
14
14
  assert_equal response[:body][:exception][:error_class], "ZeroDivisionError"
15
15
  assert_includes response[:body][:exception][:message], "divided by 0"
16
16
  assert_includes response[:body][:exception][:backtrace], "/exception_notification/test/webhook_notifier_test.rb:48"
17
-
17
+
18
18
  assert response[:body][:request][:cookies].has_key?(:cookie_item1)
19
19
  assert_equal response[:body][:request][:url], "http://example.com/example"
20
20
  assert_equal response[:body][:request][:ip_address], "192.168.1.1"
@@ -25,6 +25,16 @@ class WebhookNotifierTest < ActiveSupport::TestCase
25
25
  assert response[:body][:data][:extra_data].has_key?(:data_item1)
26
26
  end
27
27
 
28
+ test "should send webhook notification with correct params data" do
29
+ url = 'http://localhost:8000'
30
+ fake_exception.stubs(:backtrace).returns('the backtrace')
31
+ webhook = ExceptionNotifier::WebhookNotifier.new({:url => url})
32
+
33
+ HTTParty.expects(:send).with(:post, url, fake_params)
34
+
35
+ webhook.call(fake_exception)
36
+ end
37
+
28
38
  test "should call pre/post_callback if specified" do
29
39
  HTTParty.stubs(:send).returns(fake_response)
30
40
  webhook = ExceptionNotifier::WebhookNotifier.new({:url => 'http://localhost:8000'})
@@ -58,8 +68,24 @@ class WebhookNotifierTest < ActiveSupport::TestCase
58
68
  }
59
69
  end
60
70
 
71
+ def fake_params
72
+ {
73
+ :body => {
74
+ :server => Socket.gethostname,
75
+ :process => $$,
76
+ :rails_root => Rails.root,
77
+ :exception => {
78
+ :error_class => 'ZeroDivisionError',
79
+ :message => 'divided by 0'.inspect,
80
+ :backtrace => 'the backtrace'
81
+ },
82
+ :data => {}
83
+ }
84
+ }
85
+ end
86
+
61
87
  def fake_exception
62
- exception = begin
88
+ @fake_exception ||= begin
63
89
  5/0
64
90
  rescue Exception => e
65
91
  e
@@ -3,8 +3,8 @@ require 'test_helper'
3
3
  class ExceptionNotifierTest < ActiveSupport::TestCase
4
4
  test "should have default ignored exceptions" do
5
5
  assert_equal ExceptionNotifier.ignored_exceptions,
6
- ['ActiveRecord::RecordNotFound', 'AbstractController::ActionNotFound', 'ActionController::RoutingError',
7
- 'ActionController::UnknownFormat', 'ActionController::UrlGenerationError']
6
+ ['ActiveRecord::RecordNotFound', 'Mongoid::Errors::DocumentNotFound', 'AbstractController::ActionNotFound',
7
+ 'ActionController::RoutingError', 'ActionController::UnknownFormat', 'ActionController::UrlGenerationError']
8
8
  end
9
9
 
10
10
  test "should have email notifier registered" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: exception_notification
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.2.0
4
+ version: 4.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jamis Buck
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-07-12 00:00:00.000000000 Z
12
+ date: 2016-07-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: actionmailer