世界上最伟大的投资就是投资自己的教育

首页服务器部署
随风 · 练气

部署之异常捕获 (五)

随风发布于3229 次阅读

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 条回复
暂无回复~~
喜欢
统计信息
    学员: 29921
    视频数量: 1996
    文章数量: 526

© 汕尾市求知科技有限公司 | Rails365 Gitlab | 知乎 | b 站 | csdn

粤公网安备 44152102000088号粤公网安备 44152102000088号 | 粤ICP备19038915号

Top