当使用tools.logging和java.util.logging(简称JUL)时,默认情况下我们得到的日志前缀如下:
Oct 23, 2023 2:14:47 PM clojure.tools.logging$eval3668$fn__3671 invoke
请注意,所记录的类和方法名称是完全无用的。
tools.logging库推荐的解决方案是,用户应该更改日志追加器的输出格式,不要打印类和方法,而是打印日志名称,即Clojure命名空间名称。
这是一个可能解决方案,当执行日志记录的APP的作者和配置JUL的代码的作者同一个人的时候,也就是日志是在APP级别配置和执行的。
用例
我会说,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
。前者字符串信息量为0,后者使我们能够知道在何处查找执行的日志语句。
提高性能。如果调用.setSourceClassName
,则日志系统不会使用反射来确定调用类和方法。这需要遍历堆栈跟踪,是一件缓慢的事情。
即使默认/无配置的JUL也会给出关于谁在stderr中制造所有这些消息的线索,如果用户不知道这个日志库/机制。
如果需要,我可以提出一个PR来影响这一变化。