我在记录应用程序事件时遇到了这个问题。下面是要求。记录正在发生的基本应用程序事件、方法调用、它们的参数、返回、处理时间等。但只有日志文件必须包含每个请求的 3 行日志。第一行:记录请求详细信息,当请求进来时。第二行:记录所有应用程序事件(这是问题所在)第三行:记录请求销毁事件,当请求完成它的生命周期时。这三个请求由命中请求时创建的事务 ID 标识,该 ID 放在MDCof中slf4j。现在我被告知使用 aStringBuilder来附加日志记录详细信息,它应该在控制器方法中初始化,将它的引用传递给每个被调用的方法,StringBuilder在finally控制器方法块中记录内容。此实现使整个代码库变得丑陋。所以我尝试使用ThreadLocal带有 a 的 varStringBuilder来存储日志记录详细信息,并在请求被销毁时清理它以避免内存泄漏。相反,我尝试使用如下所示的实现(伪)。ThreadLocal用初始值初始化。public static ThreadLocal<StringBuilder> log = new ThreadLocal<StringBuilder>() { @Override protected StringBuilder initialValue() { return new StringBuilder("|Internal"); }};将详细信息附加到ThreadLocal本版StringBuilderSomeClass.log.get().append("|").append(whatever);所有处理完成后,在 finally 块的控制器方法中将此内容写入日志文件作为日志的第二行,然后将其清理。但是我的队友对此非常怀疑。你能告诉我在这种情况下的实施有什么问题吗(这是一个好方法)?是否存在内存泄漏等问题?对此的任何评论都非常感谢。
1 回答
德玛西亚99
TA贡献1770条经验 获得超3个赞
直接解决您的问题
从技术上讲,我看到这种方法有两个问题:
所有控制器方法都需要清理本地线程。这足以让某个地方的某个人忘记将这个 finally 块放在某个控制器中 - 事情将开始崩溃。如果不清理 StringBuilder,也会发生内存泄漏。因此,对于通过“泄漏”控制器的所有线程,数据将越来越多地累积。
如果由于某种原因 BL 在另一个线程中生成/执行,代码将中断。
现在关于功能本身。我看到了这样一个要求的两个可能的理由:
审计
计量
如果我们谈论的是计量,考虑到您已经在使用 spring boot,您可以使用 Dropwizard 指标(spring boot 1.x)或 Micrometer(spring boot 2.x,带有可向后移植到 1.5.x)
如果我们谈论的是审计,那么与支持清理所有控制器中的内容的日志记录的耦合可能会很脆弱,正如我上面所说的那样。
我想引起您注意的最后一件事是“3 行”要求。一般来说,一起检查 3 条消息并不容易,通常人们只处理 1 行日志(搜索、计数、grep 等等),而不是同时处理 3 行。我提出这个问题,因为也许它可以指出它也可以将请求日志记录和审计应用程序业务事件的要求分开。在这种情况下,也许可以使用一种技术(过滤器、tomcat 阀等)记录请求,而审计本身可以使用其他技术甚至技术来完成。
如果您必须使用现有的解决方案,一种有趣的方法可能是将日志记录重构为某些 AOP 方面/过滤器或其他一些众所周知的点,以便所有控制器都不必处理您描述的代码
添加回答
举报
0/150
提交
取消