Java 使用Log4j2从静态方法记录

Java 使用Log4j2从静态方法记录,java,osgi,log4j2,Java,Osgi,Log4j2,我试图在OSGi环境中使用Log4j2。到目前为止,我已经让它工作了,但是在检查控制台和文件中的日志时,我注意到其中一些日志丢失了,特别是从静态方法调用的日志。 下面示例中的Log类只是一个方便的类,可以让我的同事通过一个create方法更轻松地调用日志功能(在这个示例中,一个String看起来当然有些过分了)。它只是创建一个Log类的实例,该实例内部有一个从Log4j2记录器调用相应方法的Logger 我的问题是:我的项目中是否有一个简单的错误,或者Log4j2是否无法从静态方法登录到文件 下

我试图在OSGi环境中使用Log4j2。到目前为止,我已经让它工作了,但是在检查控制台和文件中的日志时,我注意到其中一些日志丢失了,特别是从静态方法调用的日志。 下面示例中的
Log
类只是一个方便的类,可以让我的同事通过一个create方法更轻松地调用日志功能(在这个示例中,一个
String
看起来当然有些过分了)。它只是创建一个Log类的实例,该实例内部有一个从Log4j2记录器调用相应方法的
Logger

我的问题是:我的项目中是否有一个简单的错误,或者Log4j2是否无法从静态方法登录到文件

下面是一个代码示例,使其更清晰:

Log log = Log.testLog();
    log.info("non static log" );
这是我从非静态方法调用的代码。 下面是
testLog()
-方法:

public static Log testLog() {
    Log.create( Log.class ).info( "static log" );
    return Log.create( Log.class );
}
结果: 这两个
#info()
调用都会写入控制台附件,但只会将“非静态日志”消息写入文件

这是我的
log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>


<Appenders>
    <Console name="Console">
        <PatternLayout pattern="!ENTRY %logger{1.} %level %d{DEFAULT} [%t]%n!MESSAGE %msg%n%n"/>
    </Console>

    <RollingFile name="RollingFile" fileName="${sys:osgi.logfile}.log4j.log"
            filePattern="${sys:osgi.logfile}.log4j_bak_%i.log">
        <PatternLayout>
            <pattern>!ENTRY %logger{1.} %level %d{DEFAULT} [%t]\n!MESSAGE %msg%n%n</pattern>
        </PatternLayout>
        <Policies>
            <SizeBasedTriggeringPolicy size="1 MB"/>
        </Policies>
        <DefaultRolloverStrategy max="10"
            fileIndex="min"/>
    </RollingFile>
  </Appenders>

  <Loggers>
    <Root level="TRACE" additivity="false">
        <AppenderRef ref="RollingFile"/>
        <AppenderRef ref="Console"/>
    </Root>
  </Loggers>
</Configuration>

!条目%logger{1.}%level%d{DEFAULT}[%t]\n!消息%msg%n%n

终于找到了我特定问题的根源,那就是OSGi(在本例中是Equinox框架)。我的应用程序使用
osgi.logfile
系统属性来指向应该保存日志的位置

不幸的是,Equinox不仅创建了该属性,而且在启动时将其更改为其他位置。对于Log4j2,我使用
${sys:osgi.logfile}
来获取这个系统属性,但是由于一些特定插件启动得太早,Log4j2仍然为这些插件配置了错误的(aka.old)位置(更具体地说:它们的
LoggerContext


在这种情况下,对我有帮助的是一个简单的
LoggerContext.reconfigure()
,位于仍然保留旧位置的
LoggerContext

为什么不调用
Log.create(Log.class)
一次呢?这会改变什么吗?这背后真的没有什么原因,我只是为了测试目的快速地将该方法组合在一起。我不确定,但我可以想象,重新创建
Log
实例可能会清除缓冲区。除此之外,我们通常在log4j周围使用一个包装器,比如slf4j或commons logging,并因此使用一个工厂来创建logger,但是AFAIK log4j提供了类似的东西,可能是出于完全相同的原因,即您应该只创建一个特定的logger,然后重用该实例。该工厂(或来自log4j2的类似构造)可以吗是
日志管理器
?如果是这样的话,这就是我的
Log
类在其核心使用的结构。正如我所说,我不是log4j专家,但听起来是这样的。在这种情况下,您可能应该发布
Log.create()
的相关部分。