背景
Tomcat的Access Log能记录所有通过Http接口的请求,方便定位问题。但由于一些周期性的调用如/admin/health,也会记录日志,会导致Access Log中很多垃圾数据,影响定位效率。
过滤规则
Tomcat支持通过配置设置Access Log过滤规则,Spring Boot是嵌入Tomcat容器,因此可以通过@Configuration的方式进行配置。
@Configuration public class WebConfig implements EmbeddedServletContainerCustomizer {
@Override public void customize(ConfigurableEmbeddedServletContainer container) { if (container instanceof TomcatEmbeddedServletContainerFactory) { TomcatEmbeddedServletContainerFactory factory = (TomcatEmbeddedServletContainerFactory) container; Collection<Valve> valves = factory.getEngineValves(); if (valves != null) { for (Valve valve : valves) { if (valve instanceof AccessLogValve) { ((AccessLogValve) valve).setConditionUnless("_no_access_log"); } } } } }
上述代码,通过Java Config的方式,配置日志规则为:除非HttpServerletRequest的_no_access_log属性不为null,否则就要记录日志。
Tomcat还支持很多配置,可以参考http://tomcat.apache.org/tomcat-5.5-doc/config/valve.html
设置过滤
@Component @Aspect public class AccessLogAspect { @Pointcut("execution(* org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(..))") public void logPointcut() { } @Before("logPointcut()") public void doBefore(JoinPoint joinPoint) throws Throwable { Object[] args = joinPoint.getArgs(); if (args == null || args.length <= 0 || !(args[0] instanceof HttpServletRequest)) { return; } HttpServletRequest request = (HttpServletRequest) args[0]; request.setAttribute("_no_access_log", "true"); } }
上述代码是一个切面,调用org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke的时候,会自动设置HttpServerletRequest的_no_access_log的输入为true。
这个函数就对应了/admin/health端点, 即对Spring Boot健康检查端点的调用不记录到Access Log中。