当使用tools.logging和java.util.logging(简称JUL)时,默认情况下,我们得到的日志前缀如下
Oct 23, 2023 2:14:47 PM clojure.tools.logging$eval3668$fn__3671 invoke
请注意,所记录的类和方法名称是完全无关紧要的。
tools.logging库推荐的做法是,用户应更改日志输出格式,以防止打印类和方法,而打印日志器名称,即Clojure命名空间名称。
当日志的作者和配置JUL的代码的作者是同一个人时,即日志是在应用程序级别配置和完成的,这是一种可能的解决方案。
用例
我会说,tools.logging更常见的用例是,库作者在使用库时并不知道最终用户使用的是哪种日志解决方案。同时,最终用户也没有意识到他们的依赖树中有这种日志存在。在这种情况下,有人构建了一个Clojure应用程序,可能有一个100个依赖。突然,他们开始在stderr中看到上面的描述。
他们可能想要
- 将其重定向到文件
- 抑制信息
- 想要知道是哪个依赖项产生了这些信息
所有这些任务都需要用户识别他们正在查看的是JUL日志,然后配置JUL以输出日志器名称来确定进行日志记录的命名空间。 他们也可能希望在Java代码中保持包含方法名的格式。
方法
使用LogRecord类强制将类名指定为Clojure命名空间。示例代码
(cond-> (doto (LogRecord. level# ~msg)
(.setLoggerName ~ns)
(.setMessage ~msg)
(.setParameters (object-array ~params))
(.setSourceClassName ~ns))
~e (doto (.setThrown ~e)))
好处
将输出中的 clojure.tools.logging$eval3668$fn__3671 invoke
替换为 my.lib.namespace
。前者字符串没有任何信息价值,后者使我们能够知道如何查找执行的日志语句。
提高了性能。如果调用 .setSourceClassName
,则日志系统不会使用反射来确定调用者类和方法。这涉及到遍历堆栈跟踪,并且很慢。
即使在默认/无配置的JUL中,它也会给出关于所有消息在stderr中的位置的提示,如果用户不知道这个日志库/机制。
如果需要,我可以提出一个的影响变更的PR。