我正在开发一个Spring启动应用程序,我想通过我的slf4j日志系统将Tomcat的访问日志路由到远程系统日志。
因为它是Spring,所以我想避免触及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中挂钩?
我也接受完全不同的建议来获取远程系统日志中的访问日志,但我们正在制作数十种微服务,因此它必须是一种非常标准化的方法,对于每个微服务都很容易实现。
答案 0 :(得分:1)
使用EmbeddedServletContainerCustomizer界面。为嵌入式tomcat添加自定义阀门。
例如
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter implements EmbeddedServletContainerCustomizer {
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
if (container instanceof TomcatEmbeddedServletContainerFactory) {
TomcatEmbeddedServletContainerFactory factory = (TomcatEmbeddedServletContainerFactory) container;
AccessLogValve accessLogValve = new Log4JAccessLogValve();
accessLogValve.setDirectory("/var/log/access_log");
accessLogValve.setPattern("%h %u %t "%r" %s %b - %T");
accessLogValve.setSuffix(".log");
factory.addContextValves(accessLogValve);
} else {
logger.error("WARNING! this customizer does not support a custom configured container");
}
}
}
答案 1 :(得分:1)
将这些答案组合成适用于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());
}
}
}
答案 2 :(得分:0)
此外,我建议使用AbstractAccessLogValve而不是AccessLogValve扩展Log4JAccessLogValve。它不会初始化AccessLogValve的文件访问日志文件相关功能
例如:
import java.io.CharArrayWriter;
import org.apache.catalina.valves.AbstractAccessLogValve;
public class Log4JAccessLogValve extends AbstractAccessLogValve {
@Override
protected void log(CharArrayWriter message) {
LOGGER.info(message.toString());
}
}