spring boot框架下如何过滤tomcat生成的访问日志
Posted
技术标签:
【中文标题】spring boot框架下如何过滤tomcat生成的访问日志【英文标题】:How to filter access logs generated by tomcat under spring boot framework 【发布时间】:2016-06-13 09:10:00 【问题描述】:我们使用的是spring boot框架,通过内嵌的tomcat生成访问日志,访问日志的格式如下:
server.tomcat.access-log-enabled=true
server.tomcat.access-log-pattern="%h %l %u %t '%r' %s %b %D"
server.tomcat.basedir=/data/logs/Waijule/SchoolService/access
幸运的是,生成的访问日志成功,我们得到了肯定的结果:
"127.0.0.1 - - [01/Mar/2016:11:25:47 +0800] 'POST /school-svc/index-summary HTTP/1.1' 200 127 21"
"127.0.0.1 - - [01/Mar/2016:11:25:47 +0800] 'POST /school-svc/wechat/signature/get HTTP/1.1' 200 238 9"
"127.0.0.1 - - [01/Mar/2016:11:25:47 +0800] 'POST /school-svc/wechat/ticket/get HTTP/1.1' 200 225 148"
为了确保服务健康,我们保持每 5 秒运行一次健康检查,我们要过滤的请求以便我们可以得到清晰的访问日志,健康检查 url 就像示例:
"127.0.0.1 - - [01/Mar/2016:12:04:10 +0800] 'GET /school-svc/isHealth HTTP/1.1' 200 6 104"
如何过滤健康检查请求?
感谢您的帮助。
根据documentation on access loging,我尝试使用conditionIf来解决问题,在我们的spring框架中,我尝试重写EmbeddedServletContainerCustomizer类中的customize函数,以便可以设置conditionIf,我们的实现喜欢以下示例:
@Configuration
public class Application implements EmbeddedServletContainerCustomizer
@Override
public void customize(ConfigurableEmbeddedServletContainer container)
if (container instanceof TomcatEmbeddedServletContainerFactory)
log.debug("It is TomcatEmbeddedServletContainerFactory");
TomcatEmbeddedServletContainerFactory factory = (TomcatEmbeddedServletContainerFactory) container;
AccessLogValve accessLogValve = new AccessLogValve();
accessLogValve.setConditionIf("ignore");
factory.addContextValves(accessLogValve);
else
log.error("WARNING! this customizer does not support your configured container");
在我的理解中,下一步我们需要做的是设置属性参数,所以我在上面的健康检查控制器上写了拦截器,实现是这样的:
@Component
@Aspect
public class HealthCheckInterceptor
@Before("execution(* com.waijule.home.controller.HealthCheckController.process(..))")
private void beforeGetHomeDetailByHomeIdWithTry(JoinPoint joinPoint)
try
Object[] args = joinPoint.getArgs();
Prediction.checkTrue(args[0] instanceof HttpServletRequest);
HttpServletRequest request = (HttpServletRequest) args[0];
request.setAttribute("ignore", "true");
catch (Exception e)
log.error(e.getMessage());
最后,检查 RequestServlet 的属性(“ignore”)是否被评估。
@RestController
@RequestMapping(value = "/home-svc/isHealth" , method = RequestMethod.GET, RequestMethod.HEAD )
public class HealthCheckController
private String HEALTH = "health";
@RequestMapping
public String process(HttpServletRequest request)
log.debug("ignore attribute is ", request.getAttribute("ignore"));
return HEALTH;
输出:忽略属性为真
但是,访问日志中仍然可以找到健康检查的访问通知:
"127.0.0.1 - - [03/Mar/2016:11:34:00 +0800] 'GET /home-svc/isHealth HTTP/1.1' 200 6 120"
我认为属性参数“忽略”是在过程后期设置的,何时以及如何为 HttpServletRequest 设置属性?
如果我们的假设不正确,是什么导致操作不起作用?
感谢您的帮助。
【问题讨论】:
你读过Tomcat的documentation on access loging,尤其是condition
的三个属性吗?这应该为您指明正确的方向。
@AndyWilkinson,我听从了你的建议,遇到了一些困难。我记录在下一个模块中,重点关注第一个答案。谢谢。
我尝试了提到的确切步骤,并且效果很好。我认为使用 setConditionIf 而不是 setConditionUnless 的解决方案存在拼写错误。即使使用了 setConditionUnless,我也不需要拦截器,我可以在方法调用本身中设置属性。
另外,我没有创建新的 AccessLogValue,而是获取了现有的 AccessLogValue 并更改了它的属性。这有助于确保我也可以从应用程序属性中设置值。
【参考方案1】:
正如对这个问题Exclude certain requests from Tomcat's log 的回复https://***.com/a/55569199/3346298 所建议的,您应该使用过滤器并将此过滤器添加到filterChain,而不是通过AOP 添加它。
出于同样的原因,似乎在执行 AOP 方面之前检查了日志/非日志功能。
PD:抱歉回复晚了
【讨论】:
以上是关于spring boot框架下如何过滤tomcat生成的访问日志的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot 过滤器顺序:WebLogic 12c vs Tomcat 8
Spring Boot框架开发的Java项目在CentOS7上的部署