SpringBoot下对Tomcat Access Log的过滤

背景

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中。

 

猜你喜欢

转载自blog.csdn.net/qq_33315102/article/details/80586532