Logback MDC - SuccessHandler 中的错误值
Logback MDC - Wrong Value in SuccessHandler
我正尝试在我的 Spring4 应用程序中通过 logback 记录某些事件。
取自 logback 文档,我有以下 UserId Filter
@Component
public class UserIdFilter implements Filter {
public static final String USERID = "userid";
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
String userName = AccessLogger.getUserName();
MDC.put(USERID, userName);
try {
filterChain.doFilter(servletRequest, servletResponse);
} finally {
MDC.remove(USERID);
}
}
@Override
public void destroy() {}
}
它根据请求将 MDC 中的用户名设置为 "userid",并将用户名正确添加到日志输出(正在发送到 ELK 堆栈)
<appender name="LOGSTASH" class="ch.qos.logback.classic.sift.SiftingAppender">
<filter class="de.app.log.PackageFilter">
<level>de.app</level>
</filter>
<discriminator>
<key>userid</key>
<defaultValue>unknown</defaultValue>
</discriminator>
<sift>
<appender name="LOGSTASH-SIFT" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>elk:5000</destination>
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
...
<mdc/>
<logstashMarkers/>
</providers>
</encoder>
</appender>
</sift>
</appender>
我也在尝试记录成功的登录,其中 "userid" 尚未在 UserIdFilter 中设置,但用户随后通过成功处理程序(在 WebSecurityConfigurerAdapter 中配置):
public class SimpleAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
private static final Logger LOG = LoggerFactory.getLogger(SimpleAuthenticationSuccessHandler.class);
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
User user = (User) authentication.getPrincipal();
String username = user.getUsername();
MDC.put(UserIdFilter.USERID, username);
LOG.info(LogEvent.LOGIN, user.toString());
MDC.remove(UserIdFilter.USERID);
redirectStrategy.sendRedirect(httpServletRequest, httpServletResponse, "/");
}
}
但是 AuthenticationSuccessHandler 似乎 运行 陷入某种并发问题,它从不同的用户获取 MDC 变量用于日志输出。结果是,某些登录事件从已登录的用户那里获取用户标识。在日志事件之后,再次通过 UserIdFilter 设置 MDC,似乎是正确的:
June 19th 2018, 15:14:35.602 | User: johndoe | event: submit | message: ChangeRequest submitted
June 19th 2018, 15:14:16.364 | User: johndoe | event: modified | message: Form modified
June 19th 2018, 15:06:47.567 | User: chris | event: login | message: de.app.User@5aa59640: Username: johndoe
June 19th 2018, 14:36:27.221 | User: chris | event: login | message: de.app.User@e7b516eb: Username: chris
-> 第 3 行:用户 johndoe 通过 MDC
获取 chris 作为登录事件的 userId
有没有人知道如何或在何处正确implement/configure?
以上解决方案有效!
我们曾尝试在 SuccessHandler 中使用 LogStashMarker 而不是 MDC,并且由于分支,MDC 解决方案尚未正确发布到生产环境中,并且标记导致了不希望的行为。这也解释了为什么我们无法在开发中重新创建行为...呃!
抱歉占用您的时间,但也许上面的代码对某些人有帮助。
我正尝试在我的 Spring4 应用程序中通过 logback 记录某些事件。 取自 logback 文档,我有以下 UserId Filter
@Component
public class UserIdFilter implements Filter {
public static final String USERID = "userid";
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
String userName = AccessLogger.getUserName();
MDC.put(USERID, userName);
try {
filterChain.doFilter(servletRequest, servletResponse);
} finally {
MDC.remove(USERID);
}
}
@Override
public void destroy() {}
}
它根据请求将 MDC 中的用户名设置为 "userid",并将用户名正确添加到日志输出(正在发送到 ELK 堆栈)
<appender name="LOGSTASH" class="ch.qos.logback.classic.sift.SiftingAppender">
<filter class="de.app.log.PackageFilter">
<level>de.app</level>
</filter>
<discriminator>
<key>userid</key>
<defaultValue>unknown</defaultValue>
</discriminator>
<sift>
<appender name="LOGSTASH-SIFT" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>elk:5000</destination>
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
...
<mdc/>
<logstashMarkers/>
</providers>
</encoder>
</appender>
</sift>
</appender>
我也在尝试记录成功的登录,其中 "userid" 尚未在 UserIdFilter 中设置,但用户随后通过成功处理程序(在 WebSecurityConfigurerAdapter 中配置):
public class SimpleAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
private static final Logger LOG = LoggerFactory.getLogger(SimpleAuthenticationSuccessHandler.class);
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
User user = (User) authentication.getPrincipal();
String username = user.getUsername();
MDC.put(UserIdFilter.USERID, username);
LOG.info(LogEvent.LOGIN, user.toString());
MDC.remove(UserIdFilter.USERID);
redirectStrategy.sendRedirect(httpServletRequest, httpServletResponse, "/");
}
}
但是 AuthenticationSuccessHandler 似乎 运行 陷入某种并发问题,它从不同的用户获取 MDC 变量用于日志输出。结果是,某些登录事件从已登录的用户那里获取用户标识。在日志事件之后,再次通过 UserIdFilter 设置 MDC,似乎是正确的:
June 19th 2018, 15:14:35.602 | User: johndoe | event: submit | message: ChangeRequest submitted
June 19th 2018, 15:14:16.364 | User: johndoe | event: modified | message: Form modified
June 19th 2018, 15:06:47.567 | User: chris | event: login | message: de.app.User@5aa59640: Username: johndoe
June 19th 2018, 14:36:27.221 | User: chris | event: login | message: de.app.User@e7b516eb: Username: chris
-> 第 3 行:用户 johndoe 通过 MDC
获取 chris 作为登录事件的 userId有没有人知道如何或在何处正确implement/configure?
以上解决方案有效!
我们曾尝试在 SuccessHandler 中使用 LogStashMarker 而不是 MDC,并且由于分支,MDC 解决方案尚未正确发布到生产环境中,并且标记导致了不希望的行为。这也解释了为什么我们无法在开发中重新创建行为...呃!
抱歉占用您的时间,但也许上面的代码对某些人有帮助。