当使用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以影响这项更改。