当前位置: 首页 > 知识库问答 >
问题:

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

马博学
2023-03-14

我有一个场景,我想通过会话ID登录到自定义Log4j Appender。换句话说,我想为一个包(例如com.foo.bar)设置一个记录器,然后追加自定义Appender。只有当一个请求带有相同的会话标识时,我才希望记录要为匹配会话标识的Appender编写的消息。当我打开日志记录时,我们必须动态地添加一个Appender,并将其名称设置为会话我想做的是有一个预先配置的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,那么“控制台”追加器就不再存在了。当我在Appender上设置名称时,我覆盖了控制台配置,似乎无法恢复,因为记录器已经初始化。

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

我已经编写了一个Appender克隆方法,但我不确定是否有更好的方法使用Log4j API实现这一点。

共有1个答案

柴飞星
2023-03-14

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

是的,你不克隆appender,你用以下行重命名它:

appender.setName(req.getSession().getId()); 

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

创建appender的深度副本后,可以使用setName重命名它并将其用作appender。

详细信息

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

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

那不是真的,因为创建新的记录器是一件事。无论如何,你都要为每个类或每个类别做。但通常,现有的log4j配置将根据应用哪个appender的包或名称来决定。但每个会话都需要一个文件,因此需要一个新的appender(它有自己的名称和文件)。

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

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更容易

事实上,创建一个新的FileAppender(布局布局,字符串文件名)可能会更容易,请参见构造函数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);

短多了,嗯?请记住,如果更改布局(也没有克隆,只是对现有布局的新引用),您将动态更改所有布局。所以,如果你需要一个新的布局,创建一个新的。

 类似资料:
  • 问题内容: 您将推荐哪些扩展,以及如何最好地配置php以创建一个对所有内容都使用utf-8编码的网站。例如… 页面输出为utf-8 表单提交以utf-8编码的数据 字符串数据的内部处理(例如,与数据库对话时)也都在utf-8中。 看来php目前无法很好地应对多字节字符集。到目前为止,我已经知道mbstring看起来像是一个重要的扩展。 这值得麻烦吗..? 问题答案: 带有Unicode内容的PHP

  • 当onPause发生时,我的线程没有停止,导致“线程已启动”logcat错误onResume,因为我无法运行两个线程实例。此时如何终止线程?我认为我需要做一些事情,比如: 但是我不能把它添加到我的气球基本暂停中,我认为上下文是错误的。所以请帮忙,代码如下所示。(代码示例会很有帮助,谢谢) 我的活动: 我的表面视图: 我的线程:公共类 GameLoopThreadBasic 扩展线程 { 私有游戏视

  • 问题内容: 在另一个线程中,我表示我喜欢通过执行以下操作来居中GUI: 但是安德鲁·汤普森(Andrew Thompson)有不同的看法,而是打电话给 想问的人想知道为什么吗? 问题答案: 在我看来,屏幕中间的一个GUI看起来是这样的。我一直在等待它们消失,真正的GUI出现! 从Java 1.5开始,我们可以使用。哪一个.. 设置此窗口是否应在下一次使该窗口可见时显示在本机窗口系统的默认位置还是当

  • 问题内容: 我有一个Serializable对象,该对象应该将java.awt.Image作为其成员。我应该如何进行序列化? (抱歉,此版本是根据不太清晰的第一版编辑的。) 问题答案: ImageIcon实现了Serializable,可用于包装Image类 http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/ImageIcon.html

  • 问题内容: 我正在尝试将地图()的内容复制到另一个地图()内,然后清除, 以便它可以在下一次迭代/循环中获取新值。问题在于,如果不清除超级地图中的参考,就无法清除地图。这是一些伪代码。 我也尝试了一些动态的东西,但显然会引发错误(无法指定为nil) 问题是如何创建关联地图?在PHP中,我只使用aSuperMap [y] [x] = aData。似乎golang没有任何明显的方法。如果我从超级地图中

  • 本文向大家介绍如何最好地在Google地图上显示HTML5地理位置的准确性?,包括了如何最好地在Google地图上显示HTML5地理位置的准确性?的使用技巧和注意事项,需要的朋友参考一下 要在Google Map上显示HTML5地理位置的准确性,请使用以下代码-