日志记录分离

有许多众所周知的用例,其中应用程序可能与其他应用程序共享环境,并且每个应用程序都需要拥有自己的独立日志记录环境。

本节的目的是讨论其中的一些案例和实现这一目标的方法。

用例

本节描述了可以使用Log4j的一些用例以及它的预期行为。

独立应用程序

独立应用程序通常相对简单。它们通常有一个捆绑的可执行文件,只需要一个日志配置。

Web应用程序

典型的web应用程序将打包为WAR文件,并将其所有依赖项包含在 web-inf/lib 中,并将其配置文件放置在类路径或web.xml中配置的位置。

确保按照说明在web应用程序中初始化Log4j2。

Java EE应用程序

Java EE应用程序将由一个或多个WAR文件组成,可能还有一些ejb,通常都打包在EAR文件中。

通常,希望有一个适用于EAR中所有组件的配置。日志记录类通常放在所有组件共享的位置,配置也需要是可共享的。确保按照说明在web应用程序中初始化Log4j 2。

“共享”Web应用程序和REST服务容器

在这个场景中,多个WAR文件被部署到一个容器中。每个应用程序都应该使用相同的日志配置,并在每个web应用程序之间共享相同的日志记录实现。当写入文件和流时,每个应用程序应该共享它们,以避免当多个组件试图通过不同的file对象、通道等写入同一个文件时可能发生的问题。

OSGi应用程序

OSGi容器在物理上将每个JAR分离到自己的ClassLoader中,从而加强了JAR的模块化,并为JAR提供了基于版本号共享代码的标准化方法。可以这么说,OSGi框架超出了本手册的范围。在OSGi容器中使用Log4j时存在一些差异。默认情况下,扫描每个JAR包以查找其自己的Log4j配置文件。与web应用范例类似,每个bundle都有自己的LoggerContext。当需要全局Log4j配置时,这可能是不希望的,因此应该用BasicContextSelector或JndiContextSelector覆盖ContextSelector。

方法

简单的方法

在应用程序中分离日志记录的最简单方法是将每个应用程序与自己的Log4j副本打包,并使用BasicContextSelector。

虽然这适用于独立应用程序,也可能适用于web应用程序和可能的Java EE应用程序,但在最后一种情况下,它根本不起作用。但是,当这种方法确实有效时,应该使用它,因为它最终是实现日志记录的最简单和最直接的方法。

使用上下文选择器

有一些模式可以使用contextselector实现所需的日志分离状态:

将日志文件放在容器的类路径中,并设置系统属性log4j2。contextSelector到org.apache.logging.log4j.core.selector.BasicContextSelector。这将使用单个配置创建单个LoggerContext,该配置将在所有应用程序之间共享。

将日志jar放在容器的类路径中,并使用默认的ClassLoaderContextSelector。按照说明在web应用程序中初始化Log4j 2。可以将每个应用程序配置为共享容器中使用的相同配置,也可以单独配置。如果在配置中将状态日志设置为debug,则会在容器中初始化日志时输出,然后在每个web应用程序中再次输出。

按照说明在web应用程序中初始化Log4j 2,并设置系统属性或servlet上下文参数log4j2。

到org.apache.logging.log4j.core.selector.JndiContextSelector。这将导致容器使用JNDI来定位每个web应用程序的LoggerContext。

确保将isLog4jContextSelectorNamed上下文参数设置为true,并设置log4jContextName和log4jConfiguration上下文参数。

注意,JndiContextSelector将不能工作,除非log4j2。enableJndiContextSelector=true设置为系统属性或环境变量。参见enableJndiContextSelector系统属性。

设置系统属性的确切方法取决于容器。对于Tomcat,编辑$CATALINA_HOME/conf/catalina.properties。有关其他web容器,请参阅文档。

参考资料

https://logging.apache.org/log4j/2.x/manual/logsep.html