【问题标题】:How do I log particular events from Rails to a log file?如何将特定事件从 Rails 记录到日志文件?
【发布时间】:2012-06-06 03:22:24
【问题描述】:

要求

我想保留特定事件的审核日志,例如:

  • 用户登录成功
  • 用户无法登录(原因:密码错误、未确认等)
  • SuperUser 修改了其他用户的详细信息(包括他们所做的更改)

此日志应包含以下详细信息:

  • 执行操作的登录用户(基于控制器的current_user
  • 正在修改的记录(如超级用户的其他用户记录)
  • 请求该操作的 IP 地址

此日志还应存储在文件系统上的文件中,而不是数据库表中,以便稍后由机器上的其他服务提取。

一些可能性

以下是我目前考虑过的方法的简短列表:

ActiveRecord::Observer

观察者提供了一种很好的分离方式来观察这些特定事件。
然后我可以让观察者附加到一个日志文件,但我不确定我能多么容易地获得这种调用的结果(例如登录失败或工作),我需要以某种方式调用控制器方法current_user查找登录用户,获取HTTP请求获取IP地址。

审计 gem(如 audited、auditable、paper_trail 等)

这些 gem 可以方便地知道如何访问当前用户和 IP 地址的控制器,但它们都记录到数据库中的审计表中。 Auditable 特别好,因为它可以审计对象上的任何方法调用,而不仅仅是 AR 回调,但我可能需要修补它以写入文件而不是数据库.. 或其他什么?

ActiveSupport::Notifications

我仍然需要阅读此内容,但我相信它提供了一种在 Rails 中订阅低级别事件的低级别方式。对于这种情况,这可能太低级了,但我需要进一步调查。

Log4r

看起来这将是一个不错的日志文件,但我认为它没有任何方式来监视事件。这只是问题的一部分。

有什么建议吗?

是否有这样做的最佳实践方式?你能推荐任何从以前的经验中学到的宝石或教训吗?还有什么我应该考虑的吗?

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    感谢大家的回复。
    Casper,我确实决定定制一些东西。

    无论如何,我明白您写入本地数据库的观点,但该项目的要求是转储日志文件,以便更精细的日志解析服务可以查询文件,甚至将它们与来自其他来源的信息相结合。

    为了从模型和控制器中获取日志,我最终制作了一个模块,我将在观察者和ApplicationController 中都包含该模块。

    模块看起来有点像这样:

    module MyEventLogger
      mattr_accessor :logged_current_user
      mattr_accessor :logged_remote_ip
    
      def log_event(message)
        @@logger ||= Logger.new(Rails.root.join('log', 'audit.log'))
        @@logger.info "#{Time.now} | #{logged_current_user}@#{logged_remote_ip} | #{message}"
      end
    
      def logged_current_user
        @@logged_current_user || "SYSTEM"
      end
    
      def logged_remote_ip
        @@logged_remote_ip || "NO IP ADDRESS"
      end
    end
    

    ApplicationController 会有:

    include MyEventLogger
    before_filter :setup_logger
    
    ...
    
    def setup_logger
      MyEventLogger.logged_current_user = current_user
      MyEventLogger.logged_ip_address = request.remote_ip
    end
    

    观察者只需include MyEventLogger 就可以访问log_event 方法以及当前用户和IP 地址。例如:

    class UserObserver < ActiveRecord::Observer
      include MyEventLogger
    
      def after_save(user)
        log_event "The User #{user} was saved by #{logged_current_user}"
      end
    
    end
    

    【讨论】:

      【解决方案2】:

      一些想法:

      审计宝石听起来最接近您想要的。如果您查看它们的源代码,它们并没有那么复杂,而且大多数似乎实际上都是围绕 Rails Observers 构建的。您可以轻松地使用他们的代码作为基础来创建您自己的专用版本。

      例如,如果您查看 Audited 的代码,您会发现存储 current_user 实际上非常简单(如果您决定推出自己的实现):

      https://github.com/collectiveidea/audited/blob/master/lib/audited/sweeper.rb

      我认为在数据库中拥有审计数据不一定是坏事。有一天,当您需要从数千个先前的交易中追踪某个复杂问题时,您实际上可能会发现这很有用。您始终可以创建一个简单的 Rake 任务,以便在需要时将数据转储为日志文件格式。

      但是我会说Log4r 非常好,我自己在几个项目中使用过它。但我没有审计类型的需求。仅用于调试和故障排除的基本日志记录。

      如果你想要的话,你也可以考虑将你自己的 Observer 类型的系统与 Log4r 驱动程序而不是 DB 驱动程序结合起来。因为这听起来有点像您可能需要在 Observer 系统提供的之外触发日志事件。这意味着您将不得不对现有 gem 进行扩展,或者使用 gem 作为基础并使用您自己的功能对其进行扩展。

      无论如何 - 我仍然认为 DB 方法实际上是一个好处,并且能够在您的审计跟踪上运行查询有点酷。这样的东西不会有什么坏处(顺便说一句,Log4r 也支持自定义“输出驱动程序”,所以即使这样也可以用来登录数据库)。

      【讨论】:

        【解决方案3】:

        只是分享我个人的经验:

        我创建了与您在此处提到的非常相似的东西。我在数据库中使用了一个表,将相关的post 请求捕获在 application_controller 中,并将信息传递给与我的日志表关联的模型。逻辑很简单,我拥有我想要的所有控制权。唯一的努力是选择/拒绝特定交易,并重组所有有用的参数以很好地适应文本字段。

        如果你决定走那条路,我很乐意分享更多细节。

        祝你好运。

        【讨论】:

          【解决方案4】:

          这样做的一种方法是,无论您想在何处运行已记录的操作,都在一个块中运行它

          我真的建议您阅读 Russ Olsen http://books.google.com/books?id=-s2xL0pVsLUC&lpg=PA219&ots=l7I3oAK3M2&dq=eloquent%20ruby%20chapter%2018&pg=PA219#v=onepage&q&f=false 撰写的 Eloquent Ruby 第 18 章,也可以阅读 Gregory Brown 的 Ruby Best Practices http://majesticseacreature.com/rbp-book/pdfs/rbp_1-0.pdf 第 2 章中的“使用块”@

          例如

          def with_logging(description)
           begin
              @logger.debug( "Starting #{description}" ) 
              yield # this is when the code in the block executes
              @logger.debug( "Completed #{description}" )
            rescue
              @logger.error( "#{description} failed!!") 
              raise
            end
          end
          
          with_logging('code example') { puts "just printing something" }
          

          另外:可能值得研究一下 graylog http://graylog2.org/about/gelf 等工具(请参阅 http://arrrrcamp.be/videos/2011/lennart-koopmann---managing-the-logs-of-your-rails-applications/ )或这些帖子 http://openmymind.net/2012/4/4/You-Really-Should-Log-Client-Side-Error/ (javascript)、https://github.com/TwP/logginghttp://amon.cx/

          【讨论】:

            猜你喜欢
            • 2013-06-10
            • 2011-02-27
            • 1970-01-01
            • 2018-02-20
            • 2018-02-26
            • 2019-01-11
            • 2011-07-25
            • 1970-01-01
            • 2023-03-22
            相关资源
            最近更新 更多