Skip to content

Commit

Permalink
Merge 290d3f9 into b04948d
Browse files Browse the repository at this point in the history
  • Loading branch information
EmilioCristalli committed Feb 19, 2019
2 parents b04948d + 290d3f9 commit 2cb40ab
Show file tree
Hide file tree
Showing 8 changed files with 465 additions and 274 deletions.
1 change: 0 additions & 1 deletion .rubocop_todo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,4 @@ Style/ClassVars:
Style/MethodMissing:
Exclude:
- 'lib/exception_notifier/email_notifier.rb'
- 'lib/exception_notifier/mattermost_notifier.rb'
- 'lib/exception_notifier/teams_notifier.rb'
1 change: 1 addition & 0 deletions lib/exception_notifier.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ module ExceptionNotifier
include ErrorGrouping

autoload :BacktraceCleaner, 'exception_notifier/modules/backtrace_cleaner'
autoload :Formatter, 'exception_notifier/modules/formatter'

autoload :Notifier, 'exception_notifier/notifier'
autoload :EmailNotifier, 'exception_notifier/email_notifier'
Expand Down
94 changes: 18 additions & 76 deletions lib/exception_notifier/google_chat_notifier.rb
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
171 changes: 40 additions & 131 deletions lib/exception_notifier/mattermost_notifier.rb
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

0 comments on commit 2cb40ab

Please sign in to comment.