Home > database >  MDC related content in tomcat access-logs
MDC related content in tomcat access-logs

Time:09-17

Can MDC related content be made available in tomcat access logs in spring boot application.

I have gone through lot of blogs but everywhere the contents of MDC are logged to application logs but not in access logs.

Is there any way to add them in tomcat access log pattern.

CodePudding user response:

Final Verdict is: Access logs don't support MDC as per date.

Found this on github which provides a work-around to enable MDC for access logs.

https://github.com/dropwizard/dropwizard/issues/2419

In this there is a jira link which elaborates on the solution.

CodePudding user response:

As explained in Tomcat's documentation the AccessLogValve does not use any traditional logging framework:

This Valve uses self-contained logic to write its log files, which can be automatically rolled over at midnight each day. (The essential requirement for access logging is to handle a large continuous stream of data with low overhead. This Valve does not use Apache Commons Logging, thus avoiding additional overhead and potentially complex configuration).

The formatting logic is in the AbstractAccessLogValve class, while the logic that writes to the actual log file is in the AccessLogValve.

The formatting pattern uses simple %c and %{param}c AccessLogElements (where c is any character and param is a string) and can be easily extended for your purposes. For example you can add an element %{key}M that returns the MDC value associated to the key key:

import org.slf4j.MDC;

public class MDCAccessLogValve extends AccessLogValve {

    @Override
    protected AccessLogElement createAccessLogElement(String name, char pattern) {
        if (pattern == 'M') {
            return new AccessLogElement() {

                @Override
                public void addElement(CharArrayWriter buf, Date date, Request request, Response response, long time) {
                    buf.append(MDC.get(name));
                }
            };
        }
        return super.createAccessLogElement(name, pattern);
    }
}

If you want to use this valve in Spring Boot instead of the standard valve, you can add the valve in a WebServerFactoryCustomizer:

    @Bean
    public WebServerFactoryCustomizer<ConfigurableTomcatWebServerFactory> accessLogCustomizer(Environment env) {
        return new WebServerFactoryCustomizer<ConfigurableTomcatWebServerFactory>() {

            @Override
            public void customize(ConfigurableTomcatWebServerFactory factory) {
                final MDCAccessLogValve valve = new MDCAccessLogValve();
                valve.setPattern(env.getProperty("server.tomcat.accesslog.pattern", "common"));
                factory.addEngineValves(valve);
            }
        };
    }
  • Related