Asif Billa
Asif Billa

Reputation: 1061

MDC is not working Properly with Log4j

Hi I want to display the logged in User ID, Hostname, ip Address etc in the log pattern. I am using log4j for the same. I am using MDC. In My main Controller I am able to see the log with the specied Pattern but in Other file log I am not able the see the Pattern, is it like I have set the MDC in some session and Put the context value again in other Controllers ? Please suggest.

log4j.properties

log4j.rootLogger=INFO,CONSOLE,R
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=C:/Logs/Test.log
log4j.appender.R.ImmediateFlush=true
log4j.appender.R.Append=true
log4j.appender.R.MaxFileSize=10MB
log4j.appender.R.MaxBackupIndex=10
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d %X{ipAddress} %X{hostName} %X{Asif}- %c - %p - %m%n

---------------------------------
MainController.java
try {
        MDC.put("Asif", "Asif");
        MDC.put("ipAddress", request.getRemoteAddr());
        MDC.put("hostName", request.getServerName());
        logger.info("Context Info : " +    MDC.get("userId")+MDC.get("ipAddress")+MDC.get("hostName"));

    } finally {
        MDC.remove("ipAddress");
        MDC.remove("hostName");
        MDC.remove("Asif");
        MDC.clear();
    }

I have other different Controllers as well. Now the logger statement inside the main Controller is displaying the context info in the log pattern but in the Other log messages in other Controller it's not displaying the Context info.

my Question. 1. Do I need to add the Context info in all the Controllers ? 2. Is there any better approach ? 3. Am I missing something ?

Upvotes: 1

Views: 9166

Answers (1)

JC Carrillo
JC Carrillo

Reputation: 1026

MDC attributes would be 'per thread.' If two controllers do not share the same thread, then they would not have the MDC attributes - which is the case you are describing.

Try the following.

Create a filter:

public class MDCFilter implements Filter {
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        try {
            MDC.put("Asif", "Asif");
            MDC.put("ipAddress", request.getRemoteAddr());
            MDC.put("hostName", request.getServerName());
            chain.doFilter(request, response);
        } finally {
            MDC.remove("ipAddress");
            MDC.remove("hostName");
            MDC.remove("Asif");
            MDC.clear();
        }
    }
}

Then map it to all servlets (web.xml)

<filter>
    <filter-name>MDCFilter</filter-name>
    <filter-class>{your package}MDCFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>MDCFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

By doing the above, every controller/servlet/endpoint will have the MDC attributes you desire.

Good Luck!

Upvotes: 1

Related Questions