日志分离

在许多众所周知的用例中,应用程序可能与其他应用程序共享环境,并且每个应用程序都需要拥有自己的独立日志记录环境。本节的目的是讨论其中的一些情况以及实现此目的的方法。

用例

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

独立应用程序

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

Web 应用程序

典型的 Web 应用程序将打包为 WAR 文件,并将包含其所有依赖项在 WEB-INF/lib 中,并将配置文件放在类路径中或 web.xml 中配置的位置。请务必遵循 在 Web 应用程序中初始化 Log4j 2 的说明

Java EE 应用程序

Java EE 应用程序将包含一个或多个 WAR 文件,以及一些 EJB,通常都打包在 EAR 文件中。通常,最好有一个适用于 EAR 中所有组件的单一配置。日志记录类通常将放置在所有组件共享的位置,并且配置也需要可共享。请务必遵循 在 Web 应用程序中初始化 Log4j 2 的说明

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

在这种情况下,多个 WAR 文件部署到单个容器中。每个应用程序都应该使用相同的日志记录配置,并在每个 Web 应用程序之间共享相同的日志记录实现。写入文件和流时,每个应用程序都应该共享它们,以避免多个组件尝试通过不同的 File 对象、通道等写入同一个文件时可能出现的问题。

OSGi 应用程序

OSGi 容器在物理上将每个 JAR 分隔到自己的类加载器中,从而强制执行 JAR 的模块化,并提供标准化的方法供 JAR 根据版本号共享代码。可以肯定地说,OSGi 框架超出了本手册的范围。在 OSGi 容器中使用 Log4j 时,有一些区别。默认情况下,将扫描每个 JAR 捆绑包以查找其自己的 Log4j 配置文件。与 Web 应用程序范式类似,每个捆绑包都有自己的 LoggerContext。由于在需要全局 Log4j 配置时这可能不可取,因此应使用 BasicContextSelectorJndiContextSelector 覆盖 ContextSelector

方法

简单方法

在应用程序中分离日志记录的最简单方法是将每个应用程序与其自己的 Log4j 副本打包在一起,并使用 BasicContextSelector。虽然这适用于独立应用程序,并且可能适用于 Web 应用程序,甚至可能适用于 Java EE 应用程序,但在最后一种情况下它根本不起作用。但是,当这种方法有效时,应该使用它,因为它最终是实现日志记录的最简单和最直接的方法。

使用上下文选择器

有几种模式可以使用 ContextSelectors 来实现所需的日志记录分离状态

  1. 将日志记录 jar 放置在容器的类路径中,并将系统属性 log4j2.contextSelector 设置为 org.apache.logging.log4j.core.selector.BasicContextSelector。这将创建一个使用单个配置的单个 LoggerContext,该配置将在所有应用程序之间共享。
  2. 将日志记录 jar 放置在容器的类路径中,并使用默认的 ClassLoaderContextSelector。遵循 在 Web 应用程序中初始化 Log4j 2 的说明。每个应用程序都可以配置为共享容器使用的相同配置,也可以单独配置。如果在配置中将状态日志记录设置为调试,则将输出容器初始化日志记录时的输出,然后在每个 Web 应用程序中再次输出。
  3. 遵循 在 Web 应用程序中初始化 Log4j 2 的说明,并将系统属性或 servlet 上下文参数 log4j2.contextSelector 设置为 org.apache.logging.log4j.core.selector.JndiContextSelector。这将导致容器使用 JNDI 来定位每个 Web 应用程序的 LoggerContext。请务必将 isLog4jContextSelectorNamed 上下文参数设置为 true,并设置 log4jContextNamelog4jConfiguration 上下文参数。请注意,除非将 log4j2.enableJndiContextSelector=true 设置为系统属性或环境变量,否则 JndiContextSelector 将不起作用。请参阅 enableJndiContextSelector 系统属性。

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