【发布时间】:2017-11-24 19:14:06
【问题描述】:
我想要做的是以下几点: 修改 logback 以在日志行上写出用户 ID 和请求 ID。 例如
2017-11-24 [userid:abcd123 - requestId:12345679] [ClassA:MethodA1] message...
2017-11-24 [userid:abcd123 - requestId:12345679] [ClassA:MethodA2] message...
2017-11-24 [userid:abcd123 - requestId:12345679] [ClassB:MethodB1] message...
请注意,requestId 保持不变,因为它是最终用户向系统发出的一个请求的一部分。
我根据几个示例创建了一个过滤器,其中展示了如何将值设置到 MDC 中。例如(https://logback.qos.ch/manual/mdc.html1)
...
@Component
public class RequestFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
String mdcData = String.format("[userId:%s | requestId:%s] ", user(), requestId());
MDC.put("mdcData", mdcData); //Referenced from logging configuration.
chain.doFilter(request, response);
} finally {
MDC.clear();
}
}
private String requestId() {
return UUID.randomUUID().toString();
}
private String user() {
return "tux";
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
}
...
如果我向休息服务发出请求,它会执行一次,而系统不会向自己发出任何额外的信息请求。这是我所期望的,我可以看到它们都包含相同 requestId 的日志条目。 如果我向我们的 Swagger 页面之一发出浏览器页面请求,则该网页会发出多个内部请求,以获取将出现在页面上的附加信息。由于对页面需要呈现的信息的所有附加请求,日志记录捕获了加载网页请求时发出的大约 20 个请求。发生这种情况时,我最终会得到 X 个日志条目,其中每个内部请求都生成一个唯一请求,并且 requestId 会为每个请求记录。这不是我的本意。
我如何确定向系统发出的请求中所创建的内部请求调用的发起部分?
我不需要一遍又一遍地为 requestId 设置 MDC 值。根据外部用户发出的第一个请求,我只需要在每次调用时设置一次。
除了请求的生命周期之外,我什至不确定你会称之为什么,但我没有找到答案。
感谢任何指导。谢谢。
编辑:链接到我那里的另一个问题,该问题仅处理识别original user request。
【问题讨论】:
-
“子调用”是什么意思?你的意思是一个给定的请求被转发了很多次,并且每次转发都会调用过滤器?如果是这样,您可以只在请求中存储一个属性,如果该属性已设置,则避免过滤。您还可以设置过滤器的调度程序类型 (docs.oracle.com/javaee/7/api/javax/servlet/annotation/…)。如果这不是您所说的“子调用”,请解释一下。
-
通过子调用,是的,系统正在对自身进行许多其他调用,这些调用正在触发过滤器。我检查了所有显示为请求的调度程序类型。我将研究属性的设置,这听起来可能是我需要的简单修复。
-
目前还不清楚您所说的“系统”和“呼叫”是什么意思。如果您有一个前端向您的服务器发送许多请求,那么就没有“子调用”之类的东西。这些只是请求,彼此独立。
-
我很抱歉。请允许我重写问题。
标签: java logback slf4j servlet-filters mdc