RestAPI 日志记录实践问题



我在记录应用程序事件时遇到了这个问题。 以下是要求。

  • 记录正在发生的基本应用程序事件、方法调用、其参数、返回、进程计时等。
  • 但对于每个请求,只有日志文件必须包含 3 个日志行。
    • 第一行:在收到请求时记录请求详细信息。
    • 第二行:记录所有应用程序事件(这是问题所在(
    • 第三行:记录请求销毁事件,当请求完成其生命周期时。

这三个请求由命中请求时创建的事务 ID 标识,该 ID 将MDCslf4j

现在我被告知使用StringBuilder来附加日志记录详细信息,该详细信息应该在控制器方法中初始化,将其引用传递给每个被调用的方法,在控制器方法的finally块中记录StringBuilder的内容。

此实现使整个代码库变得丑陋。 因此,我尝试使用带有StringBuilderThreadLocalvar 来存储日志记录详细信息,并在请求被销毁时对其进行清理以避免内存泄漏。取而代之的是,我尝试使用如下所示的实现(伪(。

使用 init 值初始化ThreadLocal

public static ThreadLocal<StringBuilder> log = new ThreadLocal<StringBuilder>() {
@Override protected StringBuilder initialValue() {
return new StringBuilder("|Internal");
}
};

将详细信息附加到此ThreadLocalEdStringBuilder

SomeClass.log.get().append("|").append(whatever);

经过所有处理后,最后控制器方法块将此内容作为日志的第二行写入日志文件,然后清理它。 然而,我的队友对此非常怀疑。

  • 您能否让我知道在这种情况下的实现是否有任何问题(这是一种好方法(?
  • 是否有任何问题,例如内存泄漏?

对此的任何评论都非常感谢。

直接回答您的问题

从技术上讲,我认为这种方法存在两个问题:

  1. 所有控制器方法都需要清理本地线程。足以让某个地方的人忘记将这个最终块放在某个控制器中 - 东西会开始破裂。 如果不清理 StringBuilder,也会发生内存泄漏。因此,对于通过"泄漏"控制器的所有线程,数据将越来越多地累积。

  2. 如果由于某种原因 BL 在另一个线程中生成/执行,代码将中断。

现在至于功能本身。我认为这种要求有两个可能的理由:

  • 审计
  • 计量

如果我们谈论的是计量,鉴于您已经在使用 Spring 启动,您可以使用 Dropwizard 指标(Spring boot 1.x(或千分尺(Spring boot 2.x,可用向后移植到 1.5.x(实现更高级的计量系统。

如果我们谈论的是审计,那么与日志记录的耦合与清理所有控制器中的内容的耦合可能是脆弱的,正如我上面所说。

最后我想提醒大家的一点,就是这个"三行"要求。一般来说,一起检查 3 条消息并不容易,通常人们使用 1 行日志(搜索、计数、grep 等(,而不是一次检查 3 行。我提出这个问题,因为也许它可以指出,也可以将请求日志记录和审核应用程序业务事件的要求分开。在这种情况下,也许可以使用一种技术(过滤器,雄猫阀,有很多东西(记录请求,而审计本身可以使用其他技术甚至技术来完成。

如果您必须使用现有解决方案,一种有趣的方法可能是将日志记录重构到某个AOP方面/过滤器或其他一些众所周知的点,这样所有控制器就不必处理您描述的代码。

最新更新