forked from rails/exception_notification
-
Notifications
You must be signed in to change notification settings - Fork 414
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
465 additions
and
274 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,100 +1,42 @@ | ||
require 'action_dispatch' | ||
require 'active_support/core_ext/time' | ||
require 'httparty' | ||
|
||
module ExceptionNotifier | ||
class GoogleChatNotifier < BaseNotifier | ||
include ExceptionNotifier::BacktraceCleaner | ||
|
||
def call(exception, opts = {}) | ||
@options = base_options.merge(opts) | ||
@exception = exception | ||
options = base_options.merge(opts) | ||
formatter = Formatter.new(exception, options) | ||
|
||
HTTParty.post( | ||
options[:webhook_url], | ||
body: { text: body }.to_json, | ||
body: { text: body(exception, formatter) }.to_json, | ||
headers: { 'Content-Type' => 'application/json' } | ||
) | ||
end | ||
|
||
private | ||
|
||
attr_reader :options, :exception | ||
|
||
def body | ||
def body(exception, formatter) | ||
text = [ | ||
header, | ||
"\nApplication: *#{formatter.app_name}*", | ||
formatter.subtitle, | ||
'', | ||
"⚠️ Error 500 in #{Rails.env} ⚠️", | ||
formatter.title, | ||
"*#{exception.message.tr('`', "'")}*" | ||
] | ||
|
||
text += message_request | ||
text += message_backtrace | ||
|
||
text.join("\n") | ||
end | ||
|
||
def header | ||
text = ["\nApplication: *#{app_name}*"] | ||
|
||
errors_text = errors_count > 1 ? errors_count : 'An' | ||
text << "#{errors_text} *#{exception.class}* occured#{controller_text}." | ||
|
||
text | ||
end | ||
|
||
def message_request | ||
return [] unless (env = options[:env]) | ||
|
||
request = ActionDispatch::Request.new(env) | ||
|
||
[ | ||
'', | ||
'*Request:*', | ||
'```', | ||
"* url : #{request.original_url}", | ||
"* http_method : #{request.method}", | ||
"* ip_address : #{request.remote_ip}", | ||
"* parameters : #{request.filtered_parameters}", | ||
"* timestamp : #{Time.current}", | ||
'```' | ||
] | ||
end | ||
|
||
def message_backtrace | ||
backtrace = exception.backtrace ? clean_backtrace(exception) : nil | ||
|
||
return [] unless backtrace | ||
|
||
text = [] | ||
|
||
text << '' | ||
text << '*Backtrace:*' | ||
text << '```' | ||
backtrace.first(3).each { |line| text << "* #{line}" } | ||
text << '```' | ||
|
||
text | ||
end | ||
|
||
def app_name | ||
@app_name ||= options[:app_name] || rails_app_name || 'N/A' | ||
end | ||
|
||
def errors_count | ||
@errors_count ||= options[:accumulated_errors_count].to_i | ||
end | ||
|
||
def rails_app_name | ||
Rails.application.class.parent_name.underscore if defined?(Rails) | ||
end | ||
if (request = formatter.request_message.presence) | ||
text << '' | ||
text << '*Request:*' | ||
text << request | ||
end | ||
|
||
def controller_text | ||
env = options[:env] | ||
controller = env ? env['action_controller.instance'] : nil | ||
if (backtrace = formatter.backtrace_message.presence) | ||
text << '' | ||
text << '*Backtrace:*' | ||
text << backtrace | ||
end | ||
|
||
" in *#{controller.controller_name}##{controller.action_name}*" if controller | ||
text.compact.join("\n") | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,163 +1,72 @@ | ||
require 'action_dispatch' | ||
require 'active_support/core_ext/time' | ||
require 'httparty' | ||
|
||
module ExceptionNotifier | ||
class MattermostNotifier | ||
include ExceptionNotifier::BacktraceCleaner | ||
|
||
class MissingController | ||
def method_missing(*args, &block); end | ||
end | ||
|
||
attr_accessor :httparty | ||
|
||
def initialize(options = {}) | ||
super() | ||
@default_options = options | ||
@httparty = HTTParty | ||
end | ||
|
||
def call(exception, options = {}) | ||
@options = options.merge(@default_options) | ||
class MattermostNotifier < BaseNotifier | ||
def call(exception, opts = {}) | ||
options = opts.merge(base_options) | ||
@exception = exception | ||
@backtrace = exception.backtrace ? clean_backtrace(exception) : nil | ||
|
||
@env = @options.delete(:env) | ||
@formatter = Formatter.new(exception, options) | ||
|
||
@application_name = @options.delete(:app_name) || Rails.application.class.parent_name.underscore | ||
@gitlab_url = @options.delete(:git_url) | ||
@username = @options.delete(:username) || 'Exception Notifier' | ||
@avatar = @options.delete(:avatar) | ||
@gitlab_url = options[:git_url] | ||
|
||
@channel = @options.delete(:channel) | ||
@webhook_url = @options.delete(:webhook_url) | ||
raise ArgumentError, "You must provide 'webhook_url' parameter." unless @webhook_url | ||
payload = { | ||
text: message_text.compact.join("\n"), | ||
username: options[:username] || 'Exception Notifier' | ||
} | ||
|
||
if @env.nil? | ||
@controller = @request_items = nil | ||
else | ||
@controller = @env['action_controller.instance'] || MissingController.new | ||
payload[:icon_url] = options[:avatar] if options[:avatar] | ||
payload[:channel] = options[:channel] if options[:channel] | ||
|
||
request = ActionDispatch::Request.new(@env) | ||
httparty_options = options.except( | ||
:avatar, :channel, :username, :git_url, :webhook_url, | ||
:env, :accumulated_errors_count, :app_name | ||
) | ||
|
||
@request_items = { url: request.original_url, | ||
http_method: request.method, | ||
ip_address: request.remote_ip, | ||
parameters: request.filtered_parameters, | ||
timestamp: Time.current } | ||
httparty_options[:body] = payload.to_json | ||
httparty_options[:headers] ||= {} | ||
httparty_options[:headers]['Content-Type'] = 'application/json' | ||
|
||
if request.session['warden.user.user.key'] | ||
current_user = User.find(request.session['warden.user.user.key'][0][0]) | ||
@request_items[:current_user] = { id: current_user.id, email: current_user.email } | ||
end | ||
end | ||
|
||
payload = message_text.merge(user_info).merge(channel_info) | ||
|
||
@options[:body] = payload.to_json | ||
@options[:headers] ||= {} | ||
@options[:headers]['Content-Type'] = 'application/json' | ||
|
||
@httparty.post(@webhook_url, @options) | ||
HTTParty.post(options[:webhook_url], httparty_options) | ||
end | ||
|
||
private | ||
|
||
def channel_info | ||
if @channel | ||
{ channel: @channel } | ||
else | ||
{} | ||
end | ||
end | ||
|
||
def user_info | ||
infos = {} | ||
|
||
infos[:username] = @username if @username | ||
infos[:icon_url] = @avatar if @avatar | ||
|
||
infos | ||
end | ||
attr_reader :formatter | ||
|
||
def message_text | ||
text = [] | ||
|
||
text += ['@channel'] | ||
text += message_header | ||
text += message_request if @request_items | ||
text += message_backtrace if @backtrace | ||
text += message_issue_link if @gitlab_url | ||
|
||
{ text: text.join("\n") } | ||
end | ||
|
||
def message_header | ||
text = [] | ||
|
||
errors_count = @options[:accumulated_errors_count].to_i | ||
text << "### :warning: Error 500 in #{Rails.env} :warning:" | ||
text << "#{errors_count > 1 ? errors_count : 'An'} *#{@exception.class}* occured" + (@controller ? " in *#{controller_and_method}*." : '.') | ||
text << "*#{@exception.message}*" | ||
|
||
text | ||
end | ||
|
||
def message_request | ||
text = [] | ||
|
||
text << '### Request' | ||
text << '```' | ||
text << hash_presentation(@request_items) | ||
text << '```' | ||
|
||
text | ||
end | ||
text = [ | ||
'@channel', | ||
"### #{formatter.title}", | ||
formatter.subtitle, | ||
"*#{@exception.message}*" | ||
] | ||
|
||
if (request = formatter.request_message.presence) | ||
text << '### Request' | ||
text << request | ||
end | ||
|
||
def message_backtrace(size = 3) | ||
text = [] | ||
if (backtrace = formatter.backtrace_message.presence) | ||
text << '### Backtrace' | ||
text << backtrace | ||
end | ||
|
||
size = @backtrace.size < size ? @backtrace.size : size | ||
text << '### Backtrace' | ||
text << '```' | ||
size.times { |i| text << '* ' + @backtrace[i] } | ||
text << '```' | ||
text << message_issue_link if @gitlab_url | ||
|
||
text | ||
end | ||
|
||
def message_issue_link | ||
text = [] | ||
|
||
link = [@gitlab_url, @application_name, 'issues', 'new'].join('/') | ||
link = [@gitlab_url, formatter.app_name, 'issues', 'new'].join('/') | ||
params = { | ||
'issue[title]' => ['[BUG] Error 500 :', | ||
controller_and_method, | ||
formatter.controller_and_action || '', | ||
"(#{@exception.class})", | ||
@exception.message].compact.join(' ') | ||
}.to_query | ||
|
||
text << "[Create an issue](#{link}/?#{params})" | ||
|
||
text | ||
end | ||
|
||
def controller_and_method | ||
if @controller | ||
"#{@controller.controller_name}##{@controller.action_name}" | ||
else | ||
'' | ||
end | ||
end | ||
|
||
def hash_presentation(hash) | ||
text = [] | ||
|
||
hash.each do |key, value| | ||
text << "* #{key} : #{value}" | ||
end | ||
|
||
text.join("\n") | ||
"[Create an issue](#{link}/?#{params})" | ||
end | ||
end | ||
end |
Oops, something went wrong.