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