I would like to keep an audit log of particular events, such as:
This log should include details such as:
current_user)This log should also be stored in a file on the filesystem, not a database table so it can be ingested by another service on the machine at a later time.
Here is a short list of the approaches I have considered so far:
Observers give a nice separated way of watching for these particular events.
I could then get the observer to append to a log file, but I'm not sure how easy I would be able to obtain the result of such a call (such as login failed or worked) and I would need to somehow call the controller method current_user to find out the logged in user and get the HTTP request to obtain the IP address.
These gems have the convenience of knowing how to get access to the controller for the current user and IP address, but they all log to an audit table in the database. Auditable is particularly nice because it can audit any method call on an object, not just an AR callback, but I may need to patch it to write to a file instead of the database.. or something?
I still need to read up on this, but I believe it offers low-level a way of subscribing to low-level events within rails. This might be too low-level for this situation, but I need to investigate further.
It seems this will make a nice log file, but I don't think it has any way of watching for events. This would only be part of the problem.
Is there a best practices way of doing this? Can you recommend any gems or lessons learned from previous experience? Anything else I should consider?
Thanks to everyone for the responses.
Casper, I did decide to build something custom.
I see your point with writing to a local db anyway, but the requirement for this project is to dump log files so a more elaborate log parsing service can interrogate the files and even combine them with information from other sources.
In order to get logging from both models and controllers, I ended up making a module that I would include in both the observers and ApplicationController.
The module looks a little something like this:
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 would have:
include MyEventLogger
before_filter :setup_logger
...
def setup_logger
  MyEventLogger.logged_current_user = current_user
  MyEventLogger.logged_ip_address = request.remote_ip
end
The observer would just have to include MyEventLogger and it would have access to the log_event method and the current user and ip address. For example:
class UserObserver < ActiveRecord::Observer
  include MyEventLogger
  def after_save(user)
    log_event "The User #{user} was saved by #{logged_current_user}"
  end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With