Logback 手册 - 第十一章:从 log4j 版本 1.x 迁移
🏷️ Logback 手册
源自:https://logback.qos.ch/manual/migrationFromLog4j.html
作者:Ceki Gülcü, Sébastien Pennec, Carl Harris
版权所有 © 2000-2022 QOS.ch Sarl本文档使用 署名 - 非商业性使用 - 相同方式共享 2.5 许可协议 许可发布
The more things change, the more they remain the same.
变化越大,越是一样。
——阿尔芬斯·卡尔,《黄蜂》
本章涉及将自定义的 log4j 1.x 组件(如附加器或布局)迁移到 logback-classic 的主题。
仅调用 log4j 1.x 客户端 API 的软件,即 org.apache.log4j
包中的 Logger
或 Category
类,可以通过 SLF4J 迁移工具 自动迁移到使用 SLF4J。要将 log4j.property 文件迁移到其 logback 等效项,可以使用 log4j.properties 转换器。
从更广泛的角度来看,log4j 和 logback-classic 密切相关。核心组件,如记录器、附加器和布局在两个框架中都存在并提供相同的用途。同样,最重要的内部数据结构,即 LoggingEvent
,在两个框架中均存在,其实现相当类似但不完全相同。值得注意的是,在 logback-classic 中,LoggingEvent
实现了 ILoggingEvent
接口。将 log4j 组件迁移到 logback-classic 所需的大部分更改与 LoggingEvent
类的实现差异有关。请放心,这些差异相当有限。如果您尽最大努力仍无法将给定的 log4j 组件迁移到 logback-classic,请在 logback-dev 邮件列表 上发布问题。logback 的开发人员应能够提供指导。
迁移 log4j 布局
让我们从迁移一个名为 TrivialLog4jLayout
的假设和非常简单的 log4j 布局开始,该布局以日志事件中包含的消息作为格式化消息返回。以下是代码。
package chapters.migrationFromLog4j;
import org.apache.log4j.Layout;
import org.apache.log4j.spi.LoggingEvent;
public class TrivialLog4jLayout extends Layout {
public void activateOptions() {
// 这里没有需要激活的选项
}
public String format(LoggingEvent loggingEvent) {
return loggingEvent.getRenderedMessage();
}
public boolean ignoresThrowable() {
return true;
}
}
logback-classic 的等效项命名为 TrivialLogbackLayout
,代码如下:
package chapters.migrationFromLog4j;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.LayoutBase;
public class TrivialLogbackLayout extends LayoutBase<ILoggingEvent> {
public String doLayout(ILoggingEvent loggingEvent) {
return loggingEvent.getMessage();
}
}
您可以看到,在 logback-classic 布局中,格式化方法的名称为 doLayout
,而在 log4j 中为 format()
。ignoresThrowable()
方法在 logback-classic 中不需要,并且没有等价项。请注意,logback-classic 布局必须扩展 LayoutBase<ILoggingEvent>
类。
activateOptions()
方法值得进一步讨论。在 log4j 中,布局将由 log4j 配置器(即 PropertyConfigurator
或 DOMConfigurator
)调用其 activateOptions()
方法,此方法在设置布局的所有选项后立即执行。因此,布局将有机会检查其选项是否一致,如果一致,则继续完全初始化自己。
在 logback-classic 中,布局必须实现 LifeCycle
接口,其中包括一个名为 start()
的方法。start()
方法相当于 log4j 的 activateOptions()
方法。
迁移 log4j 附加器
迁移附加器与迁移布局非常相似。以下是一个名为 TrivialLog4jAppender
的非常简单的附加器,它在控制台上写入其布局返回的字符串。
package chapters.migrationFromLog4j;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.spi.LoggingEvent;
public class TrivialLog4jAppender extends AppenderSkeleton {
protected void append(LoggingEvent loggingevent) {
String s = this.layout.format(loggingevent);
System.out.println(s);
}
public void close() {
// 无需执行任何操作
}
public boolean requiresLayout() {
return true;
}
}
logback-classic 的等效项命名为 TrivialLogbackAppender
,代码如下:
package chapters.migrationFromLog4j;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase;
public class TrivialLogbackAppender extends AppenderBase<ILoggingEvent> {
@Override
public void start() {
if (this.layout == null) {
addError("未为名为 [" + name + "] 的附加器设置布局。");
return;
}
super.start();
}
@Override
protected void append(ILoggingEvent loggingevent) {
// 请注意,仅当成功启动此附加器时,AppenderBase.doAppend 将调用此方法。
String s = this.layout.doLayout(loggingevent);
System.out.println(s);
}
}
比较这两个类,您应该注意到 append()
方法的内容保持不变。logback 中不使用 requiresLayout
方法,可以将其删除。在 logback 中,stop()
方法相当于 log4j 的 close()
方法。然而,在 logback-classic 中,AppenderBase
包含了 stop
的 nop 实现,对于这个简单的附加器来说已经足够了。