2014-09-22 103 views
0

我使用apache log4j进行应用程序日志记录。当我的应用程序服务器启动时,我使用log4j.xml来初始化记录器。对于每个类,我调用Loggers.getLogger(“loggername”)来获取记录实例以记录该类的详细信息。Log4j - 更改特定记录器实例的记录器级别

例如: 中的log4j.xml

<appender name="default" class="org.apache.log4j.RollingFileAppender"> 
       <param name="File" value="${log.dir}/logs/serverout.txt" /> 
       <param name ="Append" value="TRUE"/> 
       <layout class="org.apache.log4j.PatternLayout"> 
         <param name="ConversionPattern" value="%d{[HH:mm:ss:SSS]|[MM-dd-yyyy]}|[%c]|[%p]|[%L]: %m|%n"/> 
       </layout> 
       <param name="MaxFileSize" value="10MB"/> 
       <param name="MaxBackupIndex" value="100"/> 
</appender> 
<logger name="com.mypackage" additivity="false"> 
       <level value="INFO"/> 
       <appender-ref ref="default"/> 
</logger> 

而且我在每一类如何调用

private static Logger logger = Logger.getLogger(MPMyclass.class.getName()); 

我的要求: 基本上,我运行一个应用程序服务器时会有许多用户会话。每个会话都有一个唯一的sessionId。每个会话都是几个类的实例。每个类都有自己的Logger实例。如果我想为特定的类(MPMyclass)启用日志级别..我可以只获取记录器名称(com.mypackage)并设置其级别,以便它改变整体级别。但我希望这样做,以便我只能设置一个特定的会话而不是整体。 如果我有一个类名MPMyclass,有很多MPMyclass的实例,我的要求是改变该类的一个实例的记录器级别不是所有的实例。

可能的解决方案: 1.每个会话/实例都有一个唯一的sessionId。所以我可以获得/设定关卡。但是这太复杂了,因为有很多课程设置/获取会很笨拙。 2.我可以有一个Hashtable来存储每个类的实例与他们的unqiue sessionid,但它也不被推荐,因为有太多的类和类的实例它巧妙地不是一个好soln。

我正致力于通过log4j或Java设计帮助解决这个问题。请告诉我,如果有什么我可以工作的。

感谢

回答

1

我建议你写一个自定义的RollingFileAppender进行(或任何其他追加程序)来控制这件事情,并与MDC和JMX结合起来。

它应该是这个样子:

public class MyRollingFileAppender extends RollingFileAppender implements MyRollingFileAppenderMBean { 

    private final Set<String> enabledSessions = new HashSet<>(); 

    @Override 
    public synchronized void doAppend(LoggingEvent event) { 
     if (enabledSessions.contains(event.getMDC("sessionId"))) { 
      super.doAppend(event); 
     } 
    } 

    @Override 
    public synchronized void enable(String... sessionIds) throws JMException { 
     for (String sessionId : sessionIds) { 
      enabledSessions.add(sessionId); 
     } 
    } 

    @Override 
    public synchronized void disable(String... sessionIds) throws JMException { 
     // do the opposite here... 
    } 

} 

按照此链接以获取有关MDC的想法:https://blog.oio.de/2010/11/09/logging-additional-information-like-sessionid-in-every-log4j-message/

+0

除了扩展特定的appender之外,还可以使用装饰模式将此行为添加到任何appender。另请注意,这个简单的示例不允许更改日志级别,但仅用于打开/关闭日志记录。 – Pino 2014-09-22 10:51:40

+0

@Pino您可以设置Appender的Threshold属性而不是更改记录器级别。它在这里会有同样的效果。是的,在这里创建一个装饰器将是一个更通用的解决方案。 – shlomi33 2014-09-22 10:59:20

+0

@ shlomi333是的,我知道阈值属性,但你没有在你的例子中使用它。但是,即使更改此属性,也不能根据需要控制每个类的日志记录(尽管它可能足以满足实际需要)。 – Pino 2014-09-22 11:05:32

0

如果你的最终目标是很容易找到记录特定会话的条目(或特定用户),您可以自动将会话ID(或用户ID或甚至自定义事务ID)添加到每个日志条目。这可以使用Nested Diagnostic ContextMapped Diagnostic Context完成。谷歌可以为你提供很多用法示例。

如果您确实想更改特定会话使用的特定类实例的日志级别,我认为这不是一个好主意。

+0

感谢您的建议。将检查有关MDC。 – kiddo 2014-09-22 11:16:29