日志门面混用下的格式问题

介绍了日志门面 ACL 和 SLF4J 混用带来的问题和处理过程

问题

flinkx 1.11 提交中日志中有个问题:

image-20221105143311217

输出日志中既有 log4j 也有 logback。

分析

当初为了验证会使用哪个日志配置文件,在 flinkx-launcher 的资源目录中放了 3 个日志配置文件

image-20221105143644773

其中 log4j 和 logback 的 layout 配置中分别设置了 log4j 和 logback 字样。从上面的 launcher 的启动日志中,发现使用了两个日志配置文件,说明使用了两个日志实现框架,为什么会这样呢?
其中 log4j 对应的日志是

1
2
2022-07-29 15:07:40,903 log4j - 0    WARN  [main] org.apache.hadoop.util.NativeCodeLoader:Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
2022-07-29 15:07:43,483 log4j - 2580 INFO [main] org.apache.hadoop.yarn.client.api.impl.YarnClientImpl:Submitted application application_1644979452149_289296

看了类org.apache.hadoop.yarn.client.api.impl.YarnClientImpl中 logger 对象的获取,它是从 Apache Common Logging 中获取的(类org.apache.commons.logging.LogFactory;)。

关于 ACL 的解释,见文章5分钟搞定混乱的Java日志体系: 2002年8月Apache推出了JCL(Jakarta Commons Logging),也就是日志抽象层,支持运行时动态加载日志组件的实现,当然也提供一个默认实现Simple Log(在ClassLoader中进行查找,如果能找到Log4j则默认使用log4j实现,如果没有则使用JUL 实现,再没有则使用JCL内部提供的Simple Log实现)。

一句话 ACL 是一个类似 slf4j 的门面,默认使用 log4j。 看到这里,有一个猜测:既然 ACL 默认使用 log4j,类路径中存在 log4j 的 jar 包,上面日志中出现 log4j 就对了。

验证

接下来要做的是:把 flinkx 工程里面的 log4j 全部排掉,只保留 logback,同时引入一个 ACL 到 slf4j 的转换包,用于支持需要使用 ACL 的逻辑。此外:slf4j-log4j12 是 hive 的依赖中引入的,通过 exclude 方法没法排除,考虑使用 shade 插件来做排除。重新打包上传,执行看提交日志

image-20221105143819305

从中可以看到之前的日志中 log4j 字样变成了 logback,说明之前的想法是对的。