Question

I want log4j to spit out custom pattern when printing logs. Here is the scenario:

Current log4j configuration in log4j.properties:

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} - %p <%t> - %m%n

and log statement looks something like this..

08:48:03,092 - INFO <main> - some message

However, I want to add custom patterns (or whatever that lets me customize this) to include say, loginId,account for every log statement that prints.

Desired output:

08:48:03,092 - INFO <main> <abcuser:12345> - some message 

I am using slf4j with log4j bindings.

How can I achieve this? Please help.

Was it helpful?

Solution

One alternative is to use either MDC or NDC.

For example you can add your user's information to the MDC map:

public class Controller { 
   public void someControllerMethod(){
      MDC.put("user", SecurityContext.getCurrentUser().getName());
      try{
        //do your work here
      }finally{
         MDC.clear();
      }
   }
}

Then in your PatternLayout you can configure the use of the MDC value:

%d{ABSOLUTE} - %p <%t> %X{user} - %m%n

And this will guarantee that you will see the user's name in the log output:

08:48:03,092 - INFO <main> <obiwan> - some message 

--EDIT--

To address your questions:

Well, MDC is map-like structure and you get an instance of it per thread. So, most likely it uses ThreadLocal variables behind the scenes.

There is a limited number of threads in your server so, I doubt this is going to cost a lot in terms of memory. Since it is a per-thread structure, the cost of creating the object is only assumed the first time the thread is used. But anyway this is probably negligible. I guess you just should be careful no to put really big objects inside this structure and to make sure to clear it when you no longer need it.

The importance of clearing the MDC structure is the same as that of calling the remove method on a ThreadLocal variable. If you not invoke clear, then the variables kept attached to your thread, and if you are using a thread-pool, then you may end up getting invalid MDC values from the previous usage of the thread. So, ideally, there is point in you code in which you can register the variable for logging purposes and a place in your code where you know you no longer need it and you can remove it or clear the entire structure as I did.

Also, depending on what you put in the structure, if you do not clear it, it may prevent garbage collection of an unnecessary object. So, bottom line, it is best to clear it or remove what you do not need in the moment you know you no longer need it.

Ideally, you should only put here really simple objects, like strings or primitive values and by this, avoid headaches like this.

OTHER TIPS

It's possible to implement your own PatterLayout and define new characters to map account, login etc...

You can find a tutorial here

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top