exception_notification 4.6.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.
- checksums.yaml +4 -4
- data/CHANGELOG.rdoc +30 -0
- data/CONTRIBUTING.md +23 -51
- data/README.md +65 -31
- data/Rakefile +14 -7
- data/exception_notification.gemspec +36 -32
- data/lib/exception_notification/rack.rb +4 -4
- data/lib/exception_notification/rails.rb +2 -2
- data/lib/exception_notification/rake.rb +3 -7
- data/lib/exception_notification/resque.rb +2 -2
- data/lib/exception_notification/sidekiq.rb +8 -23
- data/lib/exception_notification/version.rb +1 -1
- data/lib/exception_notification.rb +3 -3
- data/lib/exception_notifier/datadog_notifier.rb +26 -26
- data/lib/exception_notifier/email_notifier.rb +34 -30
- data/lib/exception_notifier/google_chat_notifier.rb +9 -9
- data/lib/exception_notifier/hipchat_notifier.rb +12 -12
- data/lib/exception_notifier/irc_notifier.rb +6 -6
- data/lib/exception_notifier/mattermost_notifier.rb +13 -13
- data/lib/exception_notifier/modules/error_grouping.rb +5 -5
- data/lib/exception_notifier/modules/formatter.rb +12 -12
- data/lib/exception_notifier/notifier.rb +3 -3
- data/lib/exception_notifier/slack_notifier.rb +16 -16
- data/lib/exception_notifier/sns_notifier.rb +9 -9
- data/lib/exception_notifier/teams_notifier.rb +61 -57
- data/lib/exception_notifier/webhook_notifier.rb +3 -3
- data/lib/exception_notifier.rb +27 -26
- data/lib/generators/exception_notification/install_generator.rb +7 -7
- data/lib/generators/exception_notification/templates/exception_notification.rb.erb +26 -27
- metadata +41 -110
- data/Appraisals +0 -9
- data/Gemfile +0 -5
- data/Gemfile.lock +0 -352
- data/gemfiles/rails5_2.gemfile +0 -7
- data/gemfiles/rails6_0.gemfile +0 -7
- data/gemfiles/rails6_1.gemfile +0 -7
- data/gemfiles/rails7_0.gemfile +0 -7
- data/test/exception_notification/rack_test.rb +0 -106
- data/test/exception_notification/rake_test.rb +0 -38
- data/test/exception_notification/resque_test.rb +0 -54
- data/test/exception_notifier/datadog_notifier_test.rb +0 -153
- data/test/exception_notifier/email_notifier_test.rb +0 -351
- data/test/exception_notifier/google_chat_notifier_test.rb +0 -185
- data/test/exception_notifier/hipchat_notifier_test.rb +0 -218
- data/test/exception_notifier/irc_notifier_test.rb +0 -139
- data/test/exception_notifier/mattermost_notifier_test.rb +0 -251
- data/test/exception_notifier/modules/error_grouping_test.rb +0 -167
- data/test/exception_notifier/modules/formatter_test.rb +0 -152
- data/test/exception_notifier/sidekiq_test.rb +0 -34
- data/test/exception_notifier/slack_notifier_test.rb +0 -229
- data/test/exception_notifier/sns_notifier_test.rb +0 -178
- data/test/exception_notifier/teams_notifier_test.rb +0 -92
- data/test/exception_notifier/webhook_notifier_test.rb +0 -98
- data/test/exception_notifier_test.rb +0 -288
- data/test/support/exception_notifier_helper.rb +0 -14
- data/test/support/views/exception_notifier/_new_bkg_section.html.erb +0 -1
- data/test/support/views/exception_notifier/_new_bkg_section.text.erb +0 -1
- data/test/support/views/exception_notifier/_new_section.html.erb +0 -1
- data/test/support/views/exception_notifier/_new_section.text.erb +0 -1
- data/test/test_helper.rb +0 -19
@@ -15,15 +15,15 @@ module ExceptionNotifier
|
|
15
15
|
|
16
16
|
webhook_url = options.fetch(:webhook_url)
|
17
17
|
@message_opts = options.fetch(:additional_parameters, {})
|
18
|
-
@color = @message_opts.delete(:color) {
|
18
|
+
@color = @message_opts.delete(:color) { "danger" }
|
19
19
|
@notifier = Slack::Notifier.new webhook_url, options
|
20
|
-
rescue
|
20
|
+
rescue
|
21
21
|
@notifier = nil
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
25
|
def call(exception, options = {})
|
26
|
-
clean_message = exception.message.tr(
|
26
|
+
clean_message = exception.message.tr("`", "'")
|
27
27
|
attchs = attchs(exception, clean_message, options)
|
28
28
|
|
29
29
|
return unless valid?
|
@@ -32,7 +32,7 @@ module ExceptionNotifier
|
|
32
32
|
send_notice(*args) do |_msg, message_opts|
|
33
33
|
message_opts[:channel] = options[:channel] if options.key?(:channel)
|
34
34
|
|
35
|
-
@notifier.ping
|
35
|
+
@notifier.ping "", message_opts
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
@@ -64,25 +64,25 @@ module ExceptionNotifier
|
|
64
64
|
errors_count = options[:accumulated_errors_count].to_i
|
65
65
|
|
66
66
|
measure_word = if errors_count > 1
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
67
|
+
errors_count
|
68
|
+
else
|
69
|
+
/^[aeiou]/i.match?(exception_class.to_s) ? "An" : "A"
|
70
|
+
end
|
71
71
|
|
72
72
|
exception_name = "*#{measure_word}* `#{exception_class}`"
|
73
73
|
env = options[:env]
|
74
74
|
|
75
75
|
options[:headers] ||= {}
|
76
|
-
options[:headers][
|
76
|
+
options[:headers]["Content-Type"] = "application/json"
|
77
77
|
|
78
78
|
if env.nil?
|
79
79
|
data = options[:data] || {}
|
80
80
|
text = "#{exception_name} *occured in background*\n"
|
81
81
|
else
|
82
|
-
data = (env[
|
82
|
+
data = (env["exception_notifier.exception_data"] || {}).merge(options[:data] || {})
|
83
83
|
|
84
|
-
kontroller = env[
|
85
|
-
request = "#{env[
|
84
|
+
kontroller = env["action_controller.instance"]
|
85
|
+
request = "#{env["REQUEST_METHOD"]} <#{env["REQUEST_URI"]}>"
|
86
86
|
text = "#{exception_name} *occurred while* `#{request}`"
|
87
87
|
text += " *was processed by* `#{kontroller.controller_name}##{kontroller.action_name}`" if kontroller
|
88
88
|
text += "\n"
|
@@ -93,19 +93,19 @@ module ExceptionNotifier
|
|
93
93
|
|
94
94
|
def fields(clean_message, backtrace, data)
|
95
95
|
fields = [
|
96
|
-
{
|
97
|
-
{
|
96
|
+
{title: "Exception", value: clean_message},
|
97
|
+
{title: "Hostname", value: Socket.gethostname}
|
98
98
|
]
|
99
99
|
|
100
100
|
if backtrace
|
101
101
|
formatted_backtrace = "```#{backtrace.first(@backtrace_lines).join("\n")}```"
|
102
|
-
fields << {
|
102
|
+
fields << {title: "Backtrace", value: formatted_backtrace}
|
103
103
|
end
|
104
104
|
|
105
105
|
unless data.empty?
|
106
106
|
deep_reject(data, @ignore_data_if) if @ignore_data_if.is_a?(Proc)
|
107
107
|
data_string = data.map { |k, v| "#{k}: #{v}" }.join("\n")
|
108
|
-
fields << {
|
108
|
+
fields << {title: "Data", value: "```#{data_string}```"}
|
109
109
|
end
|
110
110
|
|
111
111
|
fields.concat(@additional_fields) if @additional_fields
|
@@ -37,7 +37,7 @@ module ExceptionNotifier
|
|
37
37
|
def build_subject(exception, options)
|
38
38
|
subject =
|
39
39
|
"#{options[:sns_prefix]} - #{accumulated_exception_name(exception, options)} occurred"
|
40
|
-
subject.length > 120 ? subject[0...120] +
|
40
|
+
(subject.length > 120) ? subject[0...120] + "..." : subject
|
41
41
|
end
|
42
42
|
|
43
43
|
def build_message(exception, options)
|
@@ -49,9 +49,9 @@ module ExceptionNotifier
|
|
49
49
|
else
|
50
50
|
env = options[:env]
|
51
51
|
|
52
|
-
kontroller = env[
|
53
|
-
data = (env[
|
54
|
-
request = "#{env[
|
52
|
+
kontroller = env["action_controller.instance"]
|
53
|
+
data = (env["exception_notifier.exception_data"] || {}).merge(options[:data] || {})
|
54
|
+
request = "#{env["REQUEST_METHOD"]} <#{env["REQUEST_URI"]}>"
|
55
55
|
|
56
56
|
text = "#{exception_name} occurred while #{request}"
|
57
57
|
text += " was processed by #{kontroller.controller_name}##{kontroller.action_name}\n" if kontroller
|
@@ -71,17 +71,17 @@ module ExceptionNotifier
|
|
71
71
|
errors_count = options[:accumulated_errors_count].to_i
|
72
72
|
|
73
73
|
measure_word = if errors_count > 1
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
74
|
+
errors_count
|
75
|
+
else
|
76
|
+
/^[aeiou]/i.match?(exception.class.to_s) ? "An" : "A"
|
77
|
+
end
|
78
78
|
|
79
79
|
"#{measure_word} #{exception.class}"
|
80
80
|
end
|
81
81
|
|
82
82
|
def default_options
|
83
83
|
{
|
84
|
-
sns_prefix:
|
84
|
+
sns_prefix: "[ERROR]",
|
85
85
|
backtrace_lines: 10
|
86
86
|
}
|
87
87
|
end
|
@@ -1,15 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
3
|
+
require "action_dispatch"
|
4
|
+
require "active_support/core_ext/time"
|
5
|
+
require "json"
|
6
6
|
|
7
7
|
module ExceptionNotifier
|
8
8
|
class TeamsNotifier < BaseNotifier
|
9
9
|
include ExceptionNotifier::BacktraceCleaner
|
10
10
|
|
11
11
|
class MissingController
|
12
|
-
def method_missing(*args, &block)
|
12
|
+
def method_missing(*args, &block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def respond_to_missing?(*args)
|
16
|
+
end
|
13
17
|
end
|
14
18
|
|
15
19
|
attr_accessor :httparty
|
@@ -37,15 +41,15 @@ module ExceptionNotifier
|
|
37
41
|
if @env.nil?
|
38
42
|
@controller = @request_items = nil
|
39
43
|
else
|
40
|
-
@controller = @env[
|
41
|
-
@additional_exception_data = @env[
|
44
|
+
@controller = @env["action_controller.instance"] || MissingController.new
|
45
|
+
@additional_exception_data = @env["exception_notifier.exception_data"]
|
42
46
|
request = ActionDispatch::Request.new(@env)
|
43
47
|
|
44
|
-
@request_items = {
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
48
|
+
@request_items = {url: request.original_url,
|
49
|
+
http_method: request.method,
|
50
|
+
ip_address: request.remote_ip,
|
51
|
+
parameters: request.filtered_parameters,
|
52
|
+
timestamp: Time.current}
|
49
53
|
|
50
54
|
end
|
51
55
|
|
@@ -53,7 +57,7 @@ module ExceptionNotifier
|
|
53
57
|
|
54
58
|
@options[:body] = payload.to_json
|
55
59
|
@options[:headers] ||= {}
|
56
|
-
@options[:headers][
|
60
|
+
@options[:headers]["Content-Type"] = "application/json"
|
57
61
|
@options[:debug_output] = $stdout
|
58
62
|
|
59
63
|
@httparty.post(@webhook_url, @options)
|
@@ -63,96 +67,96 @@ module ExceptionNotifier
|
|
63
67
|
|
64
68
|
def message_text
|
65
69
|
text = {
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
70
|
+
"@type" => "MessageCard",
|
71
|
+
"@context" => "http://schema.org/extensions",
|
72
|
+
"summary" => "#{@application_name} Exception Alert",
|
73
|
+
"title" => "⚠️ Exception Occurred in #{env_name} ⚠️",
|
74
|
+
"sections" => [
|
71
75
|
{
|
72
|
-
|
73
|
-
|
76
|
+
"activityTitle" => activity_title,
|
77
|
+
"activitySubtitle" => @exception.message.to_s
|
74
78
|
}
|
75
79
|
],
|
76
|
-
|
80
|
+
"potentialAction" => []
|
77
81
|
}
|
78
82
|
|
79
|
-
text[
|
80
|
-
text[
|
81
|
-
text[
|
82
|
-
text[
|
83
|
+
text["sections"].push details
|
84
|
+
text["potentialAction"].push gitlab_view_link unless @gitlab_url.nil?
|
85
|
+
text["potentialAction"].push gitlab_issue_link unless @gitlab_url.nil?
|
86
|
+
text["potentialAction"].push jira_issue_link unless @jira_url.nil?
|
83
87
|
|
84
88
|
text
|
85
89
|
end
|
86
90
|
|
87
91
|
def details
|
88
92
|
details = {
|
89
|
-
|
90
|
-
|
93
|
+
"title" => "Details",
|
94
|
+
"facts" => []
|
91
95
|
}
|
92
96
|
|
93
|
-
details[
|
94
|
-
details[
|
95
|
-
details[
|
97
|
+
details["facts"].push message_request unless @request_items.nil?
|
98
|
+
details["facts"].push message_backtrace unless @backtrace.nil?
|
99
|
+
details["facts"].push additional_exception_data unless @additional_exception_data.nil?
|
96
100
|
details
|
97
101
|
end
|
98
102
|
|
99
103
|
def activity_title
|
100
104
|
errors_count = @options[:accumulated_errors_count].to_i
|
101
105
|
|
102
|
-
"#{errors_count > 1 ? errors_count :
|
103
|
-
(@controller ? " in *#{controller_and_method}*." :
|
106
|
+
"#{(errors_count > 1) ? errors_count : "A"} *#{@exception.class}* occurred" +
|
107
|
+
(@controller ? " in *#{controller_and_method}*." : ".")
|
104
108
|
end
|
105
109
|
|
106
110
|
def message_request
|
107
111
|
{
|
108
|
-
|
109
|
-
|
112
|
+
"name" => "Request",
|
113
|
+
"value" => "#{hash_presentation(@request_items)}\n "
|
110
114
|
}
|
111
115
|
end
|
112
116
|
|
113
117
|
def message_backtrace(size = 3)
|
114
118
|
text = []
|
115
|
-
size = @backtrace.size < size ? @backtrace.size : size
|
116
|
-
text <<
|
117
|
-
size.times { |i| text <<
|
118
|
-
text <<
|
119
|
+
size = (@backtrace.size < size) ? @backtrace.size : size
|
120
|
+
text << "```"
|
121
|
+
size.times { |i| text << "* " + @backtrace[i] }
|
122
|
+
text << "```"
|
119
123
|
|
120
124
|
{
|
121
|
-
|
122
|
-
|
125
|
+
"name" => "Backtrace",
|
126
|
+
"value" => text.join(" \n").to_s
|
123
127
|
}
|
124
128
|
end
|
125
129
|
|
126
130
|
def additional_exception_data
|
127
131
|
{
|
128
|
-
|
129
|
-
|
132
|
+
"name" => "Data",
|
133
|
+
"value" => "`#{@additional_exception_data}`\n "
|
130
134
|
}
|
131
135
|
end
|
132
136
|
|
133
137
|
def gitlab_view_link
|
134
138
|
{
|
135
|
-
|
136
|
-
|
137
|
-
|
139
|
+
"@type" => "ViewAction",
|
140
|
+
"name" => "\u{1F98A} View in GitLab",
|
141
|
+
"target" => [
|
138
142
|
"#{@gitlab_url}/#{@application_name}"
|
139
143
|
]
|
140
144
|
}
|
141
145
|
end
|
142
146
|
|
143
147
|
def gitlab_issue_link
|
144
|
-
link = [@gitlab_url, @application_name,
|
148
|
+
link = [@gitlab_url, @application_name, "issues", "new"].join("/")
|
145
149
|
params = {
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
+
"issue[title]" => ["[BUG] Error 500 :",
|
151
|
+
controller_and_method,
|
152
|
+
"(#{@exception.class})",
|
153
|
+
@exception.message].compact.join(" ")
|
150
154
|
}.to_query
|
151
155
|
|
152
156
|
{
|
153
|
-
|
154
|
-
|
155
|
-
|
157
|
+
"@type" => "ViewAction",
|
158
|
+
"name" => "\u{1F98A} Create Issue in GitLab",
|
159
|
+
"target" => [
|
156
160
|
"#{link}/?#{params}"
|
157
161
|
]
|
158
162
|
}
|
@@ -160,9 +164,9 @@ module ExceptionNotifier
|
|
160
164
|
|
161
165
|
def jira_issue_link
|
162
166
|
{
|
163
|
-
|
164
|
-
|
165
|
-
|
167
|
+
"@type" => "ViewAction",
|
168
|
+
"name" => "🐞 Create Issue in Jira",
|
169
|
+
"target" => [
|
166
170
|
"#{@jira_url}/secure/CreateIssue!default.jspa"
|
167
171
|
]
|
168
172
|
}
|
@@ -172,7 +176,7 @@ module ExceptionNotifier
|
|
172
176
|
if @controller
|
173
177
|
"#{@controller.controller_name}##{@controller.action_name}"
|
174
178
|
else
|
175
|
-
|
179
|
+
""
|
176
180
|
end
|
177
181
|
end
|
178
182
|
|
@@ -189,7 +193,7 @@ module ExceptionNotifier
|
|
189
193
|
def rails_app_name
|
190
194
|
return unless defined?(Rails) && Rails.respond_to?(:application)
|
191
195
|
|
192
|
-
if ::Gem::Version.new(Rails.version) >= ::Gem::Version.new(
|
196
|
+
if ::Gem::Version.new(Rails.version) >= ::Gem::Version.new("6.0")
|
193
197
|
Rails.application.class.module_parent_name.underscore
|
194
198
|
else
|
195
199
|
Rails.application.class.parent_name.underscore
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "action_dispatch"
|
4
|
+
require "active_support/core_ext/time"
|
5
5
|
|
6
6
|
module ExceptionNotifier
|
7
7
|
class WebhookNotifier < BaseNotifier
|
@@ -26,7 +26,7 @@ module ExceptionNotifier
|
|
26
26
|
message: exception.message.inspect,
|
27
27
|
backtrace: exception.backtrace
|
28
28
|
}
|
29
|
-
options[:body][:data] = (env && env[
|
29
|
+
options[:body][:data] = (env && env["exception_notifier.exception_data"] || {}).merge(options[:data] || {})
|
30
30
|
|
31
31
|
unless env.nil?
|
32
32
|
request = ActionDispatch::Request.new(env)
|
data/lib/exception_notifier.rb
CHANGED
@@ -1,40 +1,41 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
3
|
+
require "logger"
|
4
|
+
require "active_support/core_ext/string/inflections"
|
5
|
+
require "active_support/core_ext/module/attribute_accessors"
|
6
|
+
require "exception_notifier/base_notifier"
|
7
|
+
require "exception_notifier/modules/error_grouping"
|
8
8
|
|
9
9
|
module ExceptionNotifier
|
10
10
|
include ErrorGrouping
|
11
11
|
|
12
|
-
autoload :BacktraceCleaner,
|
13
|
-
autoload :Formatter,
|
14
|
-
|
15
|
-
autoload :Notifier,
|
16
|
-
autoload :EmailNotifier,
|
17
|
-
autoload :HipchatNotifier,
|
18
|
-
autoload :WebhookNotifier,
|
19
|
-
autoload :IrcNotifier,
|
20
|
-
autoload :SlackNotifier,
|
21
|
-
autoload :MattermostNotifier,
|
22
|
-
autoload :TeamsNotifier,
|
23
|
-
autoload :SnsNotifier,
|
24
|
-
autoload :GoogleChatNotifier,
|
25
|
-
autoload :DatadogNotifier,
|
12
|
+
autoload :BacktraceCleaner, "exception_notifier/modules/backtrace_cleaner"
|
13
|
+
autoload :Formatter, "exception_notifier/modules/formatter"
|
14
|
+
|
15
|
+
autoload :Notifier, "exception_notifier/notifier"
|
16
|
+
autoload :EmailNotifier, "exception_notifier/email_notifier"
|
17
|
+
autoload :HipchatNotifier, "exception_notifier/hipchat_notifier"
|
18
|
+
autoload :WebhookNotifier, "exception_notifier/webhook_notifier"
|
19
|
+
autoload :IrcNotifier, "exception_notifier/irc_notifier"
|
20
|
+
autoload :SlackNotifier, "exception_notifier/slack_notifier"
|
21
|
+
autoload :MattermostNotifier, "exception_notifier/mattermost_notifier"
|
22
|
+
autoload :TeamsNotifier, "exception_notifier/teams_notifier"
|
23
|
+
autoload :SnsNotifier, "exception_notifier/sns_notifier"
|
24
|
+
autoload :GoogleChatNotifier, "exception_notifier/google_chat_notifier"
|
25
|
+
autoload :DatadogNotifier, "exception_notifier/datadog_notifier"
|
26
26
|
|
27
27
|
class UndefinedNotifierError < StandardError; end
|
28
28
|
|
29
29
|
# Define logger
|
30
30
|
mattr_accessor :logger
|
31
|
-
@@logger = Logger.new(
|
31
|
+
@@logger = Logger.new($stdout)
|
32
32
|
|
33
33
|
# Define a set of exceptions to be ignored, ie, dont send notifications when any of them are raised.
|
34
34
|
mattr_accessor :ignored_exceptions
|
35
35
|
@@ignored_exceptions = %w[
|
36
36
|
ActiveRecord::RecordNotFound Mongoid::Errors::DocumentNotFound AbstractController::ActionNotFound
|
37
37
|
ActionController::RoutingError ActionController::UnknownFormat ActionController::UrlGenerationError
|
38
|
+
ActionDispatch::Http::MimeNegotiation::InvalidType Rack::Utils::InvalidParameterError
|
38
39
|
]
|
39
40
|
|
40
41
|
mattr_accessor :testing_mode
|
@@ -84,7 +85,7 @@ module ExceptionNotifier
|
|
84
85
|
raise ArgumentError, "Invalid notifier '#{name}' defined as #{notifier_or_options.inspect}"
|
85
86
|
end
|
86
87
|
end
|
87
|
-
|
88
|
+
alias_method :add_notifier, :register_exception_notifier
|
88
89
|
|
89
90
|
def unregister_exception_notifier(name)
|
90
91
|
@@notifiers.delete(name)
|
@@ -126,7 +127,7 @@ module ExceptionNotifier
|
|
126
127
|
|
127
128
|
def ignored?(exception, options)
|
128
129
|
@@ignores.any? { |condition| condition.call(exception, options) }
|
129
|
-
rescue Exception => e
|
130
|
+
rescue Exception => e # standard:disable Lint/RescueException
|
130
131
|
raise e if @@testing_mode
|
131
132
|
|
132
133
|
logger.warn(
|
@@ -140,7 +141,7 @@ module ExceptionNotifier
|
|
140
141
|
|
141
142
|
condition = @@by_notifier_ignores[notifier]
|
142
143
|
condition.call(exception, options)
|
143
|
-
rescue Exception => e
|
144
|
+
rescue Exception => e # standard:disable Lint/RescueException
|
144
145
|
raise e if @@testing_mode
|
145
146
|
|
146
147
|
logger.warn(<<~"MESSAGE")
|
@@ -159,7 +160,7 @@ module ExceptionNotifier
|
|
159
160
|
def fire_notification(notifier_name, exception, options, &block)
|
160
161
|
notifier = registered_exception_notifier(notifier_name)
|
161
162
|
notifier.call(exception, options, &block)
|
162
|
-
rescue Exception => e
|
163
|
+
rescue Exception => e # standard:disable Lint/RescueException
|
163
164
|
raise e if @@testing_mode
|
164
165
|
|
165
166
|
logger.warn(
|
@@ -176,11 +177,11 @@ module ExceptionNotifier
|
|
176
177
|
register_exception_notifier(name, notifier)
|
177
178
|
rescue NameError => e
|
178
179
|
raise UndefinedNotifierError,
|
179
|
-
|
180
|
+
"No notifier named '#{name}' was found. Please, revise your configuration options. Cause: #{e.message}"
|
180
181
|
end
|
181
182
|
|
182
183
|
def from_crawler(env, ignored_crawlers)
|
183
|
-
agent = env[
|
184
|
+
agent = env["HTTP_USER_AGENT"]
|
184
185
|
Array(ignored_crawlers).any? do |crawler|
|
185
186
|
agent =~ Regexp.new(crawler)
|
186
187
|
end
|
@@ -3,18 +3,18 @@
|
|
3
3
|
module ExceptionNotification
|
4
4
|
module Generators
|
5
5
|
class InstallGenerator < ::Rails::Generators::Base
|
6
|
-
desc
|
6
|
+
desc "Creates a ExceptionNotification initializer."
|
7
7
|
|
8
|
-
source_root File.expand_path(
|
8
|
+
source_root File.expand_path("templates", __dir__)
|
9
9
|
class_option :resque,
|
10
|
-
|
11
|
-
|
10
|
+
type: :boolean,
|
11
|
+
desc: "Add support for sending notifications when errors occur in Resque jobs."
|
12
12
|
class_option :sidekiq,
|
13
|
-
|
14
|
-
|
13
|
+
type: :boolean,
|
14
|
+
desc: "Add support for sending notifications when errors occur in Sidekiq jobs."
|
15
15
|
|
16
16
|
def copy_initializer
|
17
|
-
template
|
17
|
+
template "exception_notification.rb.erb", "config/initializers/exception_notification.rb"
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
@@ -1,22 +1,21 @@
|
|
1
1
|
# Move this require to your `config/application.rb` if you want to be notified from runner commands too.
|
2
|
-
require
|
3
|
-
require
|
2
|
+
require "exception_notification/rails"
|
3
|
+
require "exception_notification/rake"
|
4
4
|
<% if options.sidekiq? %>
|
5
|
-
require
|
6
|
-
|
7
|
-
|
8
|
-
require
|
9
|
-
require 'resque/failure/redis'
|
10
|
-
require 'exception_notification/resque'
|
5
|
+
require "exception_notification/sidekiq"<% end %><% if options.resque? %>
|
6
|
+
require "resque/failure/multiple"
|
7
|
+
require "resque/failure/redis"
|
8
|
+
require "exception_notification/resque"
|
11
9
|
|
12
|
-
Resque::Failure::Multiple.classes = [Resque::Failure::Redis, ExceptionNotification::Resque]
|
13
|
-
Resque::Failure.backend = Resque::Failure::Multiple
|
14
|
-
<% end %>
|
10
|
+
Resque::Failure::Multiple.classes = [ Resque::Failure::Redis, ExceptionNotification::Resque ]
|
11
|
+
Resque::Failure.backend = Resque::Failure::Multiple<% end %>
|
15
12
|
|
16
13
|
ExceptionNotification.configure do |config|
|
17
|
-
# Ignore additional exception types.
|
18
|
-
#
|
19
|
-
#
|
14
|
+
# Ignore additional exception types. The default list of exception classes is:
|
15
|
+
# ActiveRecord::RecordNotFound Mongoid::Errors::DocumentNotFound AbstractController::ActionNotFound
|
16
|
+
# ActionController::RoutingError ActionController::UnknownFormat ActionController::UrlGenerationError
|
17
|
+
# ActionDispatch::Http::MimeNegotiation::InvalidType Rack::Utils::InvalidParameterError
|
18
|
+
# config.ignored_exceptions += %w[ActionView::TemplateError CustomError]
|
20
19
|
|
21
20
|
# Adds a condition to decide when an exception must be ignored or not.
|
22
21
|
# The ignore_if method can be invoked multiple times to add extra conditions.
|
@@ -25,33 +24,33 @@ ExceptionNotification.configure do |config|
|
|
25
24
|
# end
|
26
25
|
|
27
26
|
# Ignore exceptions generated by crawlers
|
28
|
-
# config.ignore_crawlers %w
|
27
|
+
# config.ignore_crawlers %w[Googlebot bingbot]
|
29
28
|
|
30
29
|
# Notifiers =================================================================
|
31
30
|
|
32
31
|
# Email notifier sends notifications by email.
|
33
32
|
config.add_notifier :email, {
|
34
|
-
email_prefix:
|
35
|
-
sender_address: %
|
36
|
-
exception_recipients: %w
|
33
|
+
email_prefix: "[ERROR] ",
|
34
|
+
sender_address: %("Notifier" <notifier@example.com>),
|
35
|
+
exception_recipients: %w[exceptions@example.com]
|
37
36
|
}
|
38
37
|
|
39
|
-
# Campfire notifier sends notifications to your Campfire room. Requires
|
38
|
+
# Campfire notifier sends notifications to your Campfire room. Requires "tinder" gem.
|
40
39
|
# config.add_notifier :campfire, {
|
41
|
-
# subdomain:
|
42
|
-
# token:
|
43
|
-
# room_name:
|
40
|
+
# subdomain: "my_subdomain",
|
41
|
+
# token: "my_token",
|
42
|
+
# room_name: "my_room"
|
44
43
|
# }
|
45
44
|
|
46
|
-
# HipChat notifier sends notifications to your HipChat room. Requires
|
45
|
+
# HipChat notifier sends notifications to your HipChat room. Requires "hipchat" gem.
|
47
46
|
# config.add_notifier :hipchat, {
|
48
|
-
# api_token:
|
49
|
-
# room_name:
|
47
|
+
# api_token: "my_token",
|
48
|
+
# room_name: "my_room"
|
50
49
|
# }
|
51
50
|
|
52
|
-
# Webhook notifier sends notifications over HTTP protocol. Requires
|
51
|
+
# Webhook notifier sends notifications over HTTP protocol. Requires "httparty" gem.
|
53
52
|
# config.add_notifier :webhook, {
|
54
|
-
# url:
|
53
|
+
# url: "http://example.com:5555/hubot/path",
|
55
54
|
# http_method: :post
|
56
55
|
# }
|
57
56
|
end
|