我们有200多个Spring Boot微服务,通过SLF4j作为API,使用Logback作为其默认日志记录框架。无法切换大量服务以轻松使用Log4j2。因此,对于一个非常特殊的用例,我只想在Log4j2中使用异步功能。
[不幸的是,Log4j2的自动配置始终会在后台配置使用Logback实现的SLF4LoggingContextFactory
。我试图独立于Logback框架配置Log4j2的尝试似乎不起作用。
我的问题是:
LogManager
中的静态初始值设定项)我知道Log4j2团队不建议使用程序化配置,但是将来我可以接受任何更改。也许可以添加一个API,以允许进行此类更改而无需设置VM参数或弄乱内部类。
重新配置Log4j2的原始想法不好,因为它会破坏内部使用Log4j2 API的所有依赖项的日志记录。 SLF4JLoggingContextFactory
确保所有这些日志都重定向到SLF4J所配置的任何内容(对于Spring Boot应用程序,通常为Logback)。
因此,来自上面注释的创建多个LoggingContextFactory
实例的提示使我朝着正确的方向前进。
下面的类使用Log4j2子系统实现了一个非常简单的记录器,完全独立于应用程序的其余部分:
public class MyLogger {
private static org.apache.logging.log4j.core.LoggerContext context;
private static org.apache.logging.log4j.Logger logger;
static {
org.apache.logging.log4j.core.async.AsyncLoggerContextSelector selector = new org.apache.logging.log4j.core.async.AsyncLoggerContextSelector();
org.apache.logging.log4j.core.impl.Log4jContextFactory factory = new org.apache.logging.log4j.core.impl.Log4jContextFactory(selector);
context = factory.getContext(MyLogger.class.getName(), null,null, true);
logger = context.getLogger("MyLogger");
}
public static void info(String message) {
logger.info(message);
}
}
[好处是,所有使用Log4j2作为其日志记录框架的依赖项仍将使用SLF4LoggingContextFactory
,因此所有日志都将发送到Logback子系统。仅由我的Log4jContextFactory
实例创建的特殊记录器将使用Log4j2后端。
我知道这取决于内部Log4j2 API,但是因为它包装在类MyLogger
中,所以可以隐藏内部API的任何更改。
SLF4JLoggerContextFactory是log4j-to-slf4j的一部分,它将所有Log4j API调用路由到SLF4J。目前,没有办法告诉Log4j,对于某些任意的日志记录调用,它应该使用其他实现。尽管Log4j可以发现多种实现,但它没有提供选择多个逻辑的逻辑。
如果您只有一个用例,为什么将一个服务切换为使用Log4j 2会带来问题?它不需要更改任何代码。