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. ThisValve
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
AccessLogElement
s (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);
}
};
}