3

要求

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

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

该日志应包括以下详细信息:

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

此日志还应该存储在文件系统上的文件中,而不是数据库表中,以便稍后可以由机器上的另一个服务摄取。

一些可能性

以下是我迄今为止考虑过的方法的简短列表:

活动记录::观察者

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

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

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

ActiveSupport::通知

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

日志4r

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

有什么建议吗?

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

4

4 回答 4

2

感谢大家的回复。
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
于 2012-06-08T03:57:22.337 回答
1

一些想法:

审计宝石听起来最接近您想要的。如果您查看它们的源代码,它们并没有那么复杂,而且大多数似乎实际上都是围绕 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 也支持自定义“输出驱动程序”,所以即使这样也可以用来登录数据库)。

于 2012-06-06T05:42:37.673 回答
0

只是分享我的个人经验:

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

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

祝你好运。

于 2012-06-06T03:37:36.150 回答
0

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

我真的建议看一下 Russ Olsen 的 Eloquent Ruby 第 18 章http://books.google.com/books?id=-s2xL0pVsLUC&lpg=PA219&ots=l7I3oAK3M2&dq=eloquent%20ruby%20chapter%2018&pg=PA219#v=onepage&q&f=false和可能是 Gregory Brown 的 Ruby Best Practices 第 2 章中的“使用块” http://majesticseaacreature.com/rbp-book/pdfs/rbp_1-0.pdf

例如

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/记录http://amon.cx/

于 2012-06-06T04:06:53.893 回答