1. exception_notification是什么?
在默认情况下,线上环境出了一个错误,可能会出现一行红色的字。那样很不直观,由于线上环境和本地开发环境还是有一定区别的,例如数据就不一样,所以不能保证本地开发环境没问题,线上环境也没问题的。出了错,或许我们可以查看日志,但有时候日志太大了,难于查找,也不即时,因为是出了错才找,有没有方法是这样的,一出错就把错误通知开发人员。出错就是出了异常 ,也就是通常所说的500错误,exception_notification就是把这个错误捕获起来的gem。
2. 使用exception_notification
使用exception_notification很简单,主要是看其官方readme的文档就好了。
第一步,添加gem到Gemfile文件。
gem 'exception_notification', github: 'smartinez87/exception_notification'
第二步,生成配置文件
rails g exception_notification:install
如果要使用sidekiq就用这个
rails g exception_notification:install --sidekiq
3. 结合Slack
Slack已经不仅仅是一个项目协作的交流工具了,它提供了各种各样的插件。把exception_notification捕获的异常即时发送给Slack是一个好的实践。
第一步,添加gem。
gem 'slack-notifier'
第二步,修改config/initializers/exception_notification.rb
文件的内容。
require 'exception_notification/rails'
require 'action_dispatch'
module ExceptionNotifier
class SlackNotifier
attr_accessor :slack_options
def initialize(options)
self.slack_options = options
end
def call(exception, options={})
env = options[:env]
link = env['HTTP_HOST'] + env['REQUEST_URI']
title = "#{env['REQUEST_METHOD']} <http://#{link}>\n"
message = "------------------------------------------------------------------------------------------\n"
message += "*Project:* #{Rails.application.class.parent_name}\n"
message += "*Environment:* #{Rails.env}\n"
message += "*Time:* #{Time.zone.now.strftime('%Y-%m-%d %H:%M:%S')}\n"
message += "*Exception:* `#{exception.message}`\n"
unless env.nil?
request = ActionDispatch::Request.new(env)
request_items = {:url => request.original_url,
:http_method => request.method,
:ip_address => request.remote_ip,
:parameters => request.filtered_parameters,
:timestamp => Time.current }
message += "*HTTP Method:* #{request_items[:http_method].to_s}\n"
message += "*Parameters:* #{request_items[:parameters].to_s}\n"
end
req = Rack::Request.new(env)
unless req.params.empty?
message += "*Parameters:*\n"
message += req.params.map { |k, v| ">#{k}=#{v}" }.join("\n")
message += "\n"
end
message += "*Backtrace*: \n"
message += "`#{exception.backtrace.first}`"
notifier = Slack::Notifier.new slack_options.fetch(:webhook_url),
channel: slack_options.fetch(:channel),
username: slack_options.fetch(:username),
# icon_emoji: slack_options.fetch(:icon_emoji),
attachments: [{
color: 'danger',
title: title,
text: message,
mrkdwn_in: %w(text title fallback)
}]
notifier.ping ''
end
end
end
ExceptionNotification.configure do |config|
config.ignore_if do |exception, options|
not Rails.env.production?
end
config.add_notifier :slack, {
:webhook_url => your_webhok_url,
:channel => "#development",
:username => "exception"
}
end
其中webhook_url、channel、username替换成自己的,到slack的api部分查看就好了。
4. 结合数据库
也可以把数据存到数据库中。
# coding: utf-8
# 异常通知
# lib/exception_notifier/database_notifier.rb
module ExceptionNotifier
class DatabaseNotifier
def initialize(options)
# do something with the options...
end
def call(exception, options={})
# send the notification
@title = exception.message
messages = []
messages << exception.inspect
if !exception.backtrace.blank?
messages << "\n"
messages << exception.backtrace[0,100]
end
if Rails.env.production?
Admin::ExceptionLog.delay.create(title: @title, body: messages.join("\n"))
else
Rails.logger.info "\n exception begin======================"
Rails.logger.info messages.join("\n")
Rails.logger.info "======================exception end\n"
end
end
end
end
# config/initializers/exception_notification.rb
require 'exception_notification/rails'
require 'exception_notification/sidekiq'
require "exception_notifier/database_notifier"
ExceptionNotification.configure do |config|
# config.ignored_exceptions += %w{ActionView::TemplateError}
config.add_notifier :database, {}
end
之后根据显示Admin::ExceptionLog这张表的数据就好了。