Logging Separation

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

Use Cases

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

Standalone Application

独立应用程序通常相对简单。它们通常具有一个 Binding 的可执行文件,仅需要一个日志记录配置。

Web Applications

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

Java EE 应用程序

Java EE 应用程序将由一个或多个 WAR 文件以及可能的某些 EJB(通常全部打包在 EAR 文件中)组成。通常,希望具有适用于 EAR 中所有组件的单一配置。日志记录类通常将放置在所有组件之间共享的位置,并且配置也必须是可共享的。请务必遵循在 Web 应用程序中初始化 Log4j 2 的说明

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

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

OSGi Applications

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

Approaches

简单方法

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

使用上下文 selectors

有几种模式可以使用 ContextSelector 达到所需的日志记录分离状态:

  • 将日志记录 jar 放在容器的 Classpath 中,并将系统属性 log4j2.contextSelector 设置为 org.apache.logging.log4j.core.selector.BasicContextSelector。这将使用将在所有应用程序之间共享的单个配置来创建单个 LoggerContext。

  • 将日志记录 jar 放在容器的 Classpath 中,并使用默认的 ClassLoaderContextSelector。遵循在 Web 应用程序中初始化 Log4j 2 的说明。每个应用程序可以配置为共享容器使用的相同配置,也可以单独配置。如果在配置中将状态日志记录设置为调试,则从容器中初始化日志记录开始,然后在每个 Web 应用程序中初始化日志记录时,将输出输出。

  • 遵循在 Web 应用程序中初始化 Log4j 2 的说明并将系统属性或 Servlet 上下文参数 log4j2.contextSelector 设置为 org.apache.logging.log4j.core.selector.JndiContextSelector。这将导致容器使用 JNDI 来定位每个 Web 应用程序的 LoggerContext。确保将 isLog4jContextSelectorNamed 上下文参数设置为 true,并且还要设置 log4jContextName 和 log4jConfiguration 上下文参数。

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