Reputation: 653
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?
Upvotes: 9
Views: 2507
Reputation: 313
Just adding on the Vedant's answer. Sometimed we don't need to print anything if User is not logged in. In that case:
config.log_tags = [Proc.new { |request| !request.cookie_jar.signed[:user_id].nil? ? "user_id: #{request.cookie_jar.signed[:user_id]}" : false } ]
Now the logs will have [user_id: XXXXXXXXX]
prepended when any user is logged in otherwise, nothing will be prepended.
Upvotes: 0
Reputation: 18819
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.
Upvotes: 7
Reputation: 1929
My project is using a custom logger as well, and we hook it up in environments/production.rb. Are you setting the Rails logger in production.rb?
config.logger = ActiveSupport::TaggedLogging.new(UserLogger.new)
Upvotes: 1