exception_notification 4.2.0 → 4.2.1

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: 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