Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prepend user ID to all log messages in Rails

In order to help track user actions for debugging purposes, we are considering prepending the session's logged in user ID to every log message (when applicable). Our stack consists of Rails and Authlogic. I've tried a couple of different routes, but none has been 100% successful so far.

Since Authlogic does not store the user ID in plain text in the session data, we have to wait for it to be initialized. This happens only after the ApplicationController is initialized and set to be the active Authlogic controller. We cannot rely on code in config/application.rb because of this. It seems to me the only solution is to swap out the logger at a later time.

I've attempted creating a new logger class by subclassing Logger and overwriting the add() method:

class UserLogger < Logger
  def add(severity, message = nil, progname = nil, &block)
    begin
      session = UserSession.find
    rescue
      return super(severity, message, progname, &block)
    end

    user = session.user if session

    if block_given? || !user
      return super(severity, message, progname, &block)
    end

    unless message.nil?
      message = "[#{user.id}] " + message
    end

    super severity, message, progname, &block
  end
end

This doesn't seem to have any affect on the log outpost whatsoever. I also tried messing around with TaggedLogging, but that doesn't seem to be a good solution since you have to throw any tagged code in a block.

I also tried defining config.log_tags in the application config by giving it a Proc, but Authlogic threw the same Authlogic::Session::Activation::NotActivatedError exception. Attempting to catch this exception put Ruby into a very weird state that seemed to be an infinite loop somewhere and pegged my CPU at 100%.

Is there a simple solution to this or one I am completely missing?

like image 779
Ryan LeFevre Avatar asked Nov 08 '12 20:11

Ryan LeFevre


1 Answers

It is not possible to access the session object from the request object. But you can access cookies.

So, add this code after your user login:

cookies.signed[:user_id] = @user.id

And add an initializer like:

MyApp::Application.config.log_tags = [
    -> request { "user-#{request.cookie_jar.signed[:user_id]}" }
]

Now all your logs will have [user-980191314] or [user-] prepended.

like image 127
Vedant Agarwala Avatar answered Oct 30 '22 13:10

Vedant Agarwala