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 +4 -4
- data/CHANGELOG.rdoc +10 -0
- data/README.md +5 -13
- data/exception_notification.gemspec +2 -2
- data/lib/exception_notification/rack.rb +6 -6
- data/lib/exception_notifier.rb +1 -1
- data/lib/exception_notifier/slack_notifier.rb +17 -5
- data/lib/exception_notifier/webhook_notifier.rb +2 -2
- data/lib/generators/exception_notification/templates/exception_notification.rb +1 -1
- data/test/dummy/config/boot.rb +1 -1
- data/test/dummy/config/environments/test.rb +0 -3
- data/test/exception_notifier/campfire_notifier_test.rb +8 -2
- data/test/exception_notifier/email_notifier_test.rb +2 -2
- data/test/exception_notifier/hipchat_notifier_test.rb +9 -3
- data/test/exception_notifier/irc_notifier_test.rb +1 -1
- data/test/exception_notifier/sidekiq_test.rb +11 -0
- data/test/exception_notifier/slack_notifier_test.rb +32 -4
- data/test/exception_notifier/webhook_notifier_test.rb +28 -2
- data/test/exception_notifier_test.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6de21b765af1465df6205f174cbab7e10b403048
|
4
|
+
data.tar.gz: cade5525679b528aded7b1ad6369e97f40b58947
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fe4b7770171a25a7e131d97c922e5c518531f71add293ce42359eb9f2fc84ea7330f2f935657cbf4dc13fa4a8ba2d3d492397469555d665d12d36c52603a82fd
|
7
|
+
data.tar.gz: 92774d00ec26d97246ca9d4e6334f3aac06f04c5242a555eb3a5bd5addfd8a8485bdd72787b0d304146c50e79a7ff4500aaf2a08aca744be963f3a779221b193
|
data/CHANGELOG.rdoc
CHANGED
@@ -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.
|
953
|
+
For v4.2.1, see this tag:
|
954
954
|
|
955
|
-
http://github.com/smartinez87/exception_notification/tree/v4.
|
955
|
+
http://github.com/smartinez87/exception_notification/tree/v4.2.1
|
956
956
|
|
957
|
-
For v4.
|
957
|
+
For v4.2.0, see this tag:
|
958
958
|
|
959
|
-
http://github.com/smartinez87/exception_notification/tree/v4.
|
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.
|
3
|
+
s.version = '4.2.1'
|
4
4
|
s.authors = ["Jamis Buck", "Josh Peek"]
|
5
|
-
s.date = %q{2016-07-
|
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,
|
13
|
-
|
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,
|
20
|
-
|
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,
|
27
|
-
ExceptionNotifier.register_exception_notifier(notifier_name,
|
26
|
+
options.each do |notifier_name, opts|
|
27
|
+
ExceptionNotifier.register_exception_notifier(notifier_name, opts)
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
data/lib/exception_notifier.rb
CHANGED
@@ -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
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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 |
|
44
|
-
HTTParty.send(http_method, url,
|
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.
|
data/test/dummy/config/boot.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
169
|
+
begin
|
164
170
|
raise StandardError.new('an error with <html> characters')
|
165
171
|
rescue Exception => e
|
166
172
|
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
|
-
|
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
|
-
|
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
|
-
|
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', '
|
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.
|
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
|
+
date: 2016-07-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: actionmailer
|