如何最好地复制已配置的Log4j Appender

Dal*_*ill 5 java log4j

我有一个场景,我想通过会话ID登录到自定义Log4j Appender.换句话说,我想为一个包设置一个记录器(例如com.foo.bar),然后附加自定义Appender.只有当请求带有相同的会话ID时,我才会记录要为与会话ID匹配的Appender编写的消息.当我打开日志记录时,我们必须动态添加Appender并将其名称设置为会话ID.我想要做的是有一个预先配置的Appender,我从log4j.xml文件中获取并复制它,并将名称设置为会话ID,然后将其添加到我的新记录器中.为了从配置文件中提取appender,我发现能够做到这一点的唯一方法是将一个appender附加到一个虚拟记录器(在这种情况下是support_logger)

<appender name="console" class="org.apache.log4j.ConsoleAppender">
    <param name="Target" value="System.out" />
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%-5p: %c - %m%n" />
    </layout>
</appender>

<logger name="support_logger">
    <level value="debug" />
    <appender-ref ref="console" />
</logger>
Run Code Online (Sandbox Code Playgroud)

通过这样做,我可以通过编码到达appender:

Appender appender = Logger.getLogger("support_logger").getAppender("console") );
Run Code Online (Sandbox Code Playgroud)

我现在遇到的问题是我需要创建一个新的记录器,基于我感兴趣的一些包,然后将上面的appender及其所有配置添加到新的记录器中,但设置名称Appender的会话ID.

Logger newLogger = Logger.getLogger("com.foo.bar");
appender.setName(req.getSession().getId()); 
newLogger.addAppender(appender)
Run Code Online (Sandbox Code Playgroud)

这种情况在第一次完美发生,但如果我有同一个包的另一个会话ID,那么"console"appender就不再存在了.当我在Appender上设置名称时,我覆盖了控制台配置,似乎无法将其恢复,因为记录器已经初始化.

所以我的问题是这个.我正在寻找一种简单的方法将"console"appender克隆到另一个appender并使用会话ID设置名称并保持原始的"console"记录器配置,以便我可以在后续请求中访问它.

我编写了一个Appender克隆方法,但我不确定是否有更好的方法可以使用Log4j API.

Ben*_*Ben -1

克隆对象或更改引用的对象

是的,您不克隆附加程序,而是使用以下行重命名它:

appender.setName(req.getSession().getId()); 
Run Code Online (Sandbox Code Playgroud)

在执行此操作之前,您需要创建一个深层副本。否则,您只需将现有附加程序“console”重命名为“id”。如果您需要知道如何创建深层副本,这里有一个有效的方法

创建附加程序的深层副本后,您可以使用 setName 重命名它并将其用作附加程序。

详细信息

您声称,您的新记录器就是问题所在:

我现在遇到的问题是我需要创建一个新的记录器,

这不是真的,因为创建新的 Loggers 是很困难的事情。无论如何,你要为每个班级或每个类别做。但通常情况下,现有的 log4j 配置将根据包或名称来决定应用哪个附加程序。但是每个会话都需要一个文件,因此需要一个新的附加程序(它有自己的名称文件)。

所以你实际上需要做的是这样的(伪代码):

Logger newLogger = Logger.getLogger("com.foo.bar");
FileAppender fa = null;
Appender appender = Logger.getLogger("support_logger").getAppender("console") );
try {
    fa = (FileAppender) fa;
} catch (...) {
    // TODO: put sth here
}
FileAppender sessionfileappender = AppenderUtils.deepcopy(fa);
sessionfileappender.setName(req.getSession().getId());
sessionfileappender.setFile("session-" + req.getSession().getId());
newLogger.addAppender(sessionfileappender)
Run Code Online (Sandbox Code Playgroud)

所以实际上,您需要编写 Method 代码FileAppender AppenderUtils.deepcopy(FileAppender fa)

创建新的附加程序更容易

事实上,创建一个可能更容易new FileAppender(Layout layout, String filename),请参阅构造函数 javadoc。新的伪代码将如下所示:

Logger newLogger = Logger.getLogger("com.foo.bar");
FileAppender fa = new FileAppender(
    Logger.getLogger("support_logger").getAppender("console").getLayout(),
    "session-" + req.getSession().getId());
newLogger.addAppender(fa);
Run Code Online (Sandbox Code Playgroud)

短得多吧?请记住,如果您更改布局(也不是克隆的,只是对现有布局的新引用),您将动态更改所有布局。因此,如果您需要新的布局,请创建一个新的布局。