In the production environment web application debuging is not so easy. Especially because when multiple users perform multiple actions in the same time, the output log is interleaved, and the step-by-step situation is hard to reproduce in development lab. The solution for that can be by injecting user name into the log, and then "grepping" the source log in looking for particular user paths.
If you use log4j as your logging framework the implementation is not very obvious, but can be achieved using custom PatternLayout, injecting additional variables to the logs. Here I'm presenting such class and config. We want to inject transparently hostname and username into the logs.
First the configuration (using log4j xml config). The only important is appender part:
<appender name="consoleAppender" class="org.apache.log4j.ConsoleAppender"> <layout class="ContextPatternLayout"> <param name="ConversionPattern" value="%d %p %h %u [%c] - %m %n"/> </layout> </appender>
As you can see there're here two additional (regarding original PatternLayout) parameters: %h representing hostname, and %u representing username.
Now the implementation. All in one class with some anonymous members, to be as simple as possible:
import java.net.InetAddress; import java.net.UnknownHostException; import org.apache.log4j.helpers.PatternConverter; import org.apache.log4j.helpers.PatternParser; import org.apache.log4j.spi.LoggingEvent; /** * Context pattern layout with %h (hostname) and %u (username) variables. */ public class ContextPatternLayout extends PatternLayout { protected String host; protected String getUsername() { return "username"; } protected String getHostname() { if (host==null) { try { InetAddress addr = InetAddress.getLocalHost(); this.host = addr.getHostName(); } catch (UnknownHostException e) { this.host = "localhost"; } } return host; } @Override protected PatternParser createPatternParser(String pattern) { return new PatternParser(pattern) { @Override protected void finalizeConverter(char c) { PatternConverter pc = null; switch (c) { case 'u': pc = new PatternConverter() { @Override protected String convert(LoggingEvent event) { return getUsername(); } }; break; case 'h': pc = new PatternConverter() { @Override protected String convert(LoggingEvent event) { return getHostname(); } }; break; } if (pc==null) super.finalizeConverter(c); else addConverter(pc); } }; } }
I like this site very much because it is innovative. More innovative things are there to read. Thanks for sharing.
ReplyDeletethis is not working sir
DeleteThank You Very much. I have been looking for this on the web for too long. :)
ReplyDeleteThank!!!!!!
ReplyDeletecool beans
ReplyDeleteNot working for tomcat 8.5 and websphere 8.5
ReplyDelete