我正在开发Spring Boot应用程序,我想通过slf4j日志记录系统将Tomcat的访问日志路由到远程syslog。
既然是春天,我想避免触摸tomcat的server.xml文件。
我的AccessLogValve非常简单:
import java.io.CharArrayWriter; import org.apache.catalina.valves.AccessLogValve; public class Log4JAccessLogValve extends AccessLogValve { @Override public void log(CharArrayWriter message) { log.info(message.toString()); } }
我希望可以使用这样的方法将其连接到Tomcat:
@Component public class LogConfig { @Autowired private ServletContext servletContext; @PostConstruct public void setAccessLogValve() { ((ApplicationContextFacade)servletContext).addValve(new Log4JAccessLogValve()); } }
除了addValve()方法不存在…
所以…任何人都知道我如何可以连接AccessLogValve?
对于开放访问日志到远程syslog的建议,我也持完全不同的态度,但是我们正在制作数十种微服务,因此它必须是一种非常标准化的方法,对于每个微服务都必须易于实现。
将这些答案结合到适用于springboot 2.0的东西中
import org.apache.catalina.valves.AbstractAccessLogValve; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.stereotype.Component; import java.io.CharArrayWriter; /** * see https://www.baeldung.com/embeddedservletcontainercustomizer-configurableembeddedservletcontainer-spring-boot * */ @Component @Slf4j public class CustomizeEmbeddedTomcatContainer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> { @Override public void customize(TomcatServletWebServerFactory factory) { log.info("configuring embedded Tomcat"); TomcatSlf4jAccessValve accessLogValve = new TomcatSlf4jAccessValve(); accessLogValve.setEnabled(true); /** * for pattern format see https://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/valves/AccessLogValve.html */ accessLogValve.setPattern("request: method=%m uri=\"%U\" response: statuscode=%s bytes=%b duration=%D(ms) client: remoteip=%a user=%u useragent=\"%{User-Agent}i\""); factory.addContextValves(accessLogValve); } public static class TomcatSlf4jAccessValve extends AbstractAccessLogValve { Logger httpAccessLogLogger = LoggerFactory.getLogger("http_access_log"); @Override protected void log(CharArrayWriter message) { httpAccessLogLogger.info(message.toString()); } } }