我有一个场景,我希望通过会话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>
通过这样做,我可以通过编码来获取appender:
Appender appender = Logger.getLogger("support_logger").getAppender("console") );
我现在遇到的问题是我需要创建一个新的记录器,基于我感兴趣的一些包,然后将上面的appender及其所有配置添加到新的记录器中,但是将Appender的名称设置为会话ID。
Logger newLogger = Logger.getLogger("com.foo.bar");
appender.setName(req.getSession().getId());
newLogger.addAppender(appender)
这种情况在第一次完美发生,但如果我有同一个包的另一个会话ID,那么“console”appender就不再存在了。当我在Appender上设置名称时,我覆盖了控制台配置,似乎无法将其恢复,因为记录器已经初始化。
所以我的问题是这个。我正在寻找一种简单的方法将“console”appender克隆到另一个appender并使用会话ID设置名称并保持原始的“console”记录器配置,以便我可以在后续请求中访问它。
我编写了一个Appender克隆方法,但我不确定是否有更好的方法可以使用Log4j API。
答案 0 :(得分:0)
克隆对象或更改引用的对象
是的,你没有克隆appender,你用以下行重命名它:
appender.setName(req.getSession().getId());
在执行此操作之前,您需要创建一个深层副本。否则,您只需将现有的appender“console”重命名为“id”。如果您需要知道如何创建深层副本,here is an efficient way。
创建appender的深层副本后,可以使用setName重命名它并将其用作appender。
详细信息
您声称,新记录器是您的问题:
我现在遇到的问题是我需要创建一个新的记录器,
这不是真的,因为创建新的记录器是......无论如何,你要为每个班级或每个类别做。但通常,现有的log4j配置将根据包或名称决定哪个appender将适用。但是每个会话需要一个文件,因此需要一个新的appender(它自己的Name AND 文件)。
所以你真正需要做的就是这样(伪代码):
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)
所以实际上,您需要对方法FileAppender AppenderUtils.deepcopy(FileAppender fa)
进行编码。
创建新的appender更容易
事实上,创建new FileAppender(Layout layout, String filename)
可能更容易,请参阅constructor javadoc。新的Pseudocode将是这样的:
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);
更短,嗯?请记住,如果您更改布局(既未克隆,也只是对现有布局的新引用),您将动态更改所有布局。因此,如果您需要新的布局,请创建一个新布局。