rails错误日志记录

阅读更多
Rails中对日志的处理采用的是“消息-订阅”机制,各部分组件和功能如下:

消息发送:ActiveSupport::Notifications
instrument: 通知subscribers
消息订阅:ActiveSupport::LogSubscriber


require 'active_support/configurable'

module RailsLog
  include ActiveSupport::Configurable

  configure do |config|
    config.ignore_exception = [
      'ActionController::UnknownFormat'
    ]
    config.constraint = -> (req){ User.find_by(id: req.env['rack.session']['user_id'])&.admin? }
  end

end


module RailsLog
  class ControllerSubscriber < ActiveSupport::LogSubscriber

    def header_processing(event)
      return unless logger.debug?

      payload = event.payload
      headers  = request_headers(payload[:env])

      debug "  Headers: #{headers.inspect}"
    end

    def process_action(event)
      payload = event.payload
      if payload[:exception].present?
        unless RailsLog.config.ignore_exception.include? payload[:exception_object].class.to_s
          lc = LogRecord.new
          lc.path = payload[:path]
          lc.controller = payload[:controller]
          lc.action = payload[:action]
          lc.params = payload[:params].except('controller', 'action')
          lc.headers = request_headers payload[:headers]
          lc.cookie = payload[:headers]['rack.request.cookie_hash']
          lc.session = payload[:headers]['rack.session'].to_hash
          lc.exception = payload[:exception].join("\r\n")
          lc.exception_object = payload[:exception_object].class.to_s
          lc.exception_backtrace = payload[:exception_object].backtrace.join("\r\n")
          lc.save
          info 'exception log saved!'
        end
      end
    end

    def logger
      ActionController::Base.logger
    end

    def request_headers(env)
      result = env.select { |k, _| k.start_with?('HTTP_') && k != 'HTTP_COOKIE' }
      result = result.collect { |pair| [pair[0].sub(/^HTTP_/, ''), pair[1]] }
      result.sort.to_h
    end

  end
end

RailsLog::ControllerSubscriber.attach_to :action_controller



发送邮件的时候记录日志
class ApplicationMailer < ActionMailer::Base

  def process(method_name, *args)
    payload = {
      mailer: self.class.name,
      action: method_name,
      message_object_id: self.message.object_id,
      params: args
    }

    ActiveSupport::Notifications.instrument('record.action_mailer', payload)

    super
  end

  def self.deliver_mail(mail)
    ActiveSupport::Notifications.instrument('deliver.action_mailer') do |payload|
      set_payload_for_mail(payload, mail)
      payload[:message_object_id] = mail.object_id

      result = yield

      if result.is_a? Net::SMTP::Response
        payload[:sent_status] = result.status
        payload[:sent_string] = result.string
      end
    end
  end

end


-------

module RailsLog
  class MailerSubscriber < ActiveSupport::LogSubscriber

    def record(event)
      payload = event.payload

      log_mailer = LogMailer.new(message_object_id: payload[:message_object_id], mailer: payload[:mailer])
      log_mailer.action = payload[:action]
      log_mailer.params = payload[:params]
      log_mailer.save

      info 'mailer log saved!'
    end

    def deliver(event)
      payload = event.payload

      log_mailer = LogMailer.find_or_initialize_by(message_object_id: payload[:message_object_id], mailer: payload[:mailer])
      log_mailer.sent_status = payload[:sent_status]
      log_mailer.sent_string = payload[:sent_string]
      log_mailer.save

      info 'mailer log updated!'
    end

  end
end

RailsLog::MailerSubscriber.attach_to :action_mailer

你可能感兴趣的:(rails)