首页服务器部署
2cb463fb78222ea7be096ee66e1674a0

部署之异常捕获 (五)

hfpp2012发布于307 次阅读

1. exception_notification是什么?

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_urlchannelusername替换成自己的,到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这张表的数据就好了。

本站文章均为原创内容,如需转载请注明出处,谢谢。

0 条评论
暂无评论~~
喜欢