how to log user info ?

My web-application is based on Spring MVC, Hibernate, Acegi Security etc.

Problem: My logs give me a lot information, but I can't figure out which messages where made by the same user. I want to be able to track actions done by one user.

Solution: use log4j MDC

The solution below is taken from work made by Matthias Gartner and is described here: Java HTTP User Name Log4j MDC Servlet Filter.

Because I use Acegi Security, I need to change this fragment:

HttpServletRequest httprequest = (HttpServletRequest) request;
Principal user = httprequest.getUserPrincipal();

into this:

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
LoggedUser user = null;
if ( authentication != null ) {
  user = (LoggedUser) authentication.getPrincipal();
}

(LoggedUser is my prioprietery class, you'll probably put UserDetails here, if you don't mess with Acegi the way I do).

Now, change logj4.properties, adding %X{whatever} to your pattern, where "whatever" is exactly the key you added to MDC. So if your filter does:

MDC.put( "user", "[" + user.getId() + " " + user.getFullname() + "]" );

then your log4j pattern should include:

%X{user}

Well, that's all there is to do to make it work, now you are able to see who is responsible for each action:

2007-01-20 11:41:02,219 DEBUG (AbstractFormController.java:showNewForm:322) [1 Ian McCoy] Displaying new form
2007-01-20 11:41:02,312 DEBUG (AbstractFormController.java:getErrorsForNewForm:355) [1 Ian McCoy] Binding to new form
2007-01-20 11:41:02,325 INFO  (CaseSearchDAOImpl.java:getCurrentCases:39) [1 Ian McCoy] query: SELECT * FROM someTable WHERE something >= someOtherThing
2007-01-20 11:51:06,206 INFO  (SearchDAOImpl.java:doInHibernate:453) [3 John Union] criterias: [someSecretCriteriasThatICan'tShowYouSorry]

With a little bit of programming (grep/perl or what you like) you can extract only those lines, which includes information about the user you care about.

I was thinking about other possible solutions. It's obvious to me, that you can do the same thing using AspectJ (filters behave just like around advice, don't they ?). Simply catch all calls to log(String someLog) method and stick user data to someLog parameters. But as I'm glad with the MDC/filter solution, I don't find it necessary to think about anything else.

Links

 
 
 
This used to be my blog. I moved to http://tomek.kaczanowscy.pl long time ago.

 
 
 

Please comment using