是否有以可预测的方式重新配置log4j2的机制?

时间:2018-02-02 20:20:13

标签: log4j2

我正在寻找配置/重新配置log4j的方法,可能会或者可能没有初始化。这应该可以独立运行或在Web容器中运行。

配置可以由特定任意URI处的配置文件表示。 URI的知识来自应用程序,而不是log4j框架。配置也可以通过编程方式完成(问题较少,但仍有问题)。

遗憾的是,公共API非常缺乏,因此开发人员不得不使用log4j核心的实现类来编写脆弱的代码。从研究文档和单步执行log4j代码开始,我看到了两种完成重新配置的方法:

  1. 使用log4j.core.config.Configurator停止当前上下文并重新初始化,
  2. 类似于以下内容:

      ((LoggerContext) LogManager.getContext(false)).stop();
      Configurator.initialize(buildDefaultConfiguration()); //programmatically building a configuration
    

      ((LoggerContext) LogManager.getContext(false)).stop();
      Configurator.initialize(null, ConfigurationSource.fromUri(loggingUri)); //passing the configuration source constructed from a known URI
    

    如果已经创建并启动了当前上下文(例如,在Web容器中运行时),则两个示例中的第一行将停止当前上下文。如果log4j尚未初始化(例如作为独立应用程序运行时),它将使用默认配置初始化log4j并首先启动上下文(作为调用getContext()的副作用),然后将其停止。

    如果当前上下文未停止,则首先调用Configurator.initialize()将不起作用。 log4j将忽略您重新初始化的尝试,不会给您任何指示,只是简单地返回当前上下文。 "重新配置Log4j使用ConfigurationBuilder和Configurator"中没有提到这种行为。手册的一节。它只是说:"但是,如果在调用Configurator.initialize()之前尝试任何日志记录,那么默认配置将用于那些日志事件。"默认配置也将用于所提供示例中的所有后续日志事件,因为调用Configurator.initialize()将不起作用,除非首先停止当前上下文。

    1. 在现有上下文中设置新配置位置,从而强制重新配置,
    2. 类似于以下内容:

        ((LoggerContext) LogManager.getContext(false)).setConfigLocation(loggingUri);
      

      这以类似的方式工作:如果log4j尚未初始化,则对getContext()的调用将触发初始化并创建默认上下文,然后重新配置;如果它已被初始化,那么当前的上下文,无论它可能是什么,都将被重新配置。配置源将由log4j框架从URI创建。

      不同之处在于,第一种方式是替换上下文,旧(停止)上下文中的所有记录器都将死亡。如果堆栈上的任何代码保存对这些死记录器的引用并尝试记录它们,则它将是无操作。在第二种方式中保留上下文,但替换配置并使用新配置更新现有记录器。

      这两种方法都使用核心代码,因此很脆弱,但两者都适用于晴天场景(无论如何使用log4j-core 2.10.0)。但是,似乎没有人能够为用户提供对处理任何异常事件的任何控制,或者甚至告知用户出现了问题。 Log4j会#34;吃掉"任何例外情况,并自行决定如何处理它们。

      如果在调用Configurator.initialize()之后出现问题,log4j将创建一个默认配置,有效地将除错误之外的所有日志记录切换到控制台,并愉快地返回新的上下文,而不是给调用代码任何线索,即日志记录具有有效地被阻止了。

      如果在调用LoggerContext.setConfigLocation()之后出现问题,log4j将基本上做同样的事情,除了保留当前上下文。人们会认为,特别是在重新配置失败的情况下,最典型的处理方式是恢复到旧配置。似乎没有办法实现这一点,因为log4j只会停止记录(除了错误到控制台)并且不给调用代码指示失败。

      这是一个典型的场景:几个应用程序扩展了一个通用框架。该框架为所有扩展应用程序配置相同的日志记录(以便于重用和简化日志的后处理)。某些应用程序具有唯一的日志记录需求,并尝试从其自己的元数据(已知URI的配置文件)重新配置log4j。 XML解析器抛出解析此文件的异常。 log4j在内部处理异常,日志记录被静静地停止,没有人知道。好吧,有一个错误日志发送到StatusLogger,但有例外,但调用代码不知道。

      因此,使用这个冗长的序言,问题是:是否有一种机制我还没有发现以可预测的方式修改log4j配置并能够处理异常事件?也就是说,除了(如上例所示)扩展XML配置类并替换处理异常的代码之类的东西之外,因此存在在当前log4j实现中产生不良副作用的风险,而不是在谈论更大的破坏风险将来,如果实施发生变化。

      非常感谢任何帮助!

0 个答案:

没有答案