用Log4j实现线程独立日志

用Log4j实现线程独立日志

  (2012-11-16 17:16:39)

需求:

      在一个项目里,我使用Log4j生成日志,我不希望任务线程组各个线程都记录在同一个日志里,那样太乱了,而是单独生成日志记录。这样的话,需要针对每个 线程创建Logger实例,实例名应对应线程名,而每个Logger实例的文件名应分别对应于实例名或者线程名。

 

思想:

      在网上搜了很多文章后,我还是找不到在配置文件里根据Logger实例以变量形式设置动态File的方法。那么只能打源码的主意了。打开 org.apache.log4j.DailyRollingFileAppender 的源码简单分析了一下:DailyRollingFileAppender 继承了FileAppender类,它个构造方法是 DailyRollingFileAppender(Layout layout, String filename, String datePattern),那么可以写个自定义的Appender继承DailyRollingFileAppender,在构造方法里直接将 filename设成当前线程名;再将Appender、layout的参数设置及与Logger的绑定封装在一个静态方法里就可以达到目的了。

 

具体代码:

 

自定义Appender

Java代码   收藏代码
  1. package threadlogger.appender;  
  2.   
  3. import java.io.File;  
  4. import java.io.IOException;  
  5.   
  6. import org.apache.log4j.DailyRollingFileAppender 
  7. import org.apache.log4j.Layout;  
  8.   
  9.   
  10. public class ThreadSeperateDailyRollingFileAppender extends  
  11.         DailyRollingFileAppender  
  12.  
  13.     public ThreadSeperateDailyRollingFileAppender() {}  
  14.       
  15.     public ThreadSeperateDailyRollingFileAppender(Layout layout, String datePattern) throws IOException  
  16.      
  17.         // 改动只有这点:以线程名命名日志文件  
  18.         super(layout,  
  19.                 "log" File.separator Thread.currentThread().getName(),  
  20.                 datePattern);  
  21.      
  22.  

 

 封装获得线程独立日志的Logger实例的类:

Java代码   收藏代码
  1. package threadlogger;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import org.apache.log4j.ConsoleAppender;  
  6. import org.apache.log4j.Level;  
  7. import org.apache.log4j.Logger;  
  8. import org.apache.log4j.PatternLayout;  
  9.   
  10. import threadlogger.appender.ThreadSeperateDailyRollingFileAppender;  
  11.   
  12.   
  13. public class ThreadLogger  
  14.  
  15.     ThreadLogger() {};  
  16.   
  17.     public static Logger getLogger()  
  18.      
  19.         Logger logger null 
  20.         // 创建一个Logger实例, 就以线程名命名  
  21.         logger Logger.getLogger(Thread.currentThread().getName());  
  22.           
  23.         PatternLayout layout new PatternLayout("%-4r %-5p [%d{yyyy-MM-dd HH:mm:ss,SSS}] %l%t: %m%n");  
  24.   
  25.         // 控制台输出  
  26.         ConsoleAppender concoleAppender new ConsoleAppender(layout, "System.out");  
  27.   
  28.         // 文件输出  
  29.         ThreadSeperateDailyRollingFileAppender null 
  30.         try  
  31.          
  32.             new ThreadSeperateDailyRollingFileAppender(layout, "'.'yyyy-MM-dd'.log'");  
  33.          
  34.         catch (IOException e)  
  35.          
  36.             e.printStackTrace();  
  37.          
  38.         // 参数配置, 因为没有找到仅靠配置文件的办法, 只好放在这里设  
  39.         R.setAppend(false);  
  40.         R.setImmediateFlush(true);  
  41.         R.setThreshold(Level.WARN);  
  42.   
  43.         // 绑定到Logger  
  44.         logger.setLevel(Level.DEBUG);  
  45.         logger.addAppender(concoleAppender);  
  46.         logger.addAppender(R);  
  47.           
  48.         return logger;  
  49.      
  50.   
  51.  

 测试例程:package testlog;

Java代码   收藏代码
  1. import org.apache.log4j.Logger;  
  2.   
  3. import threadlogger.ThreadLogger;  
  4.   
  5.   
  6. public class TestLog  
  7.  
  8.     // 这是主线程的Logger,这些不需独立日志的类也可以创建为普通的Logger,通过配置文件配置参数  
  9.     static Logger logger ThreadLogger.getLogger();  
  10.   
  11.     public TestLog() {}  
  12.   
  13.       
  14.     public static void main(String[] args)  
  15.      
  16.         logger.warn(TestLog.class started!");  
  17.           
  18.         ThreadBody threadBody new ThreadBody();  
  19.         for(int i=0i<</span>5++i)  
  20.             new Thread(threadBody).start();  
  21.          
  22.   
  23.         logger.debug("this is debug");  
  24.         logger.info("this is info");  
  25.         logger.warn("this is warn");  
  26.         logger.error("this is error");  
  27.      
  28.   
  29.  
  30.   
  31. class ThreadBody implements Runnable  
  32.  
  33.     public ThreadBody() {}  
  34.   
  35.       
  36.     @Override  
  37.     public void run()  
  38.      
  39.         // 注意线程独立的Logger实例要在run方法内实现  
  40.         Logger logger ThreadLogger.getLogger();  
  41.           
  42.         logger.warn(Thread.currentThread().getName() started!");  
  43.           
  44.         logger.debug("this is debug");  
  45.         logger.info("this is info");  
  46.         logger.warn("this is warn");  
  47.         logger.error("this is error");  
  48.   
  49.         logger.warn(Thread.currentThread().getName() finished!");  
  50.      
  51.       
  52.  

 

测试结果:

 

控制台输出代码   收藏代码
  1. 0    WARN  [2012-11-05 14:31:40,227testlog.TestLog.main(TestLog.java:21)main: class testlog.TestLog started!  
  2. 27   DEBUG [2012-11-05 14:31:40,254testlog.TestLog.main(TestLog.java:28)main: this is debug  
  3. 27   INFO  [2012-11-05 14:31:40,254testlog.TestLog.main(TestLog.java:29)main: this is info  
  4. 27   WARN  [2012-11-05 14:31:40,254testlog.TestLog.main(TestLog.java:30)main: this is warn  
  5. 28   ERROR [2012-11-05 14:31:40,255testlog.TestLog.main(TestLog.java:31)main: this is error  
  6. 30   WARN  [2012-11-05 14:31:40,257testlog.ThreadBody.run(TestLog.java:49)Thread-1Thread-1 started!  
  7. 33   WARN  [2012-11-05 14:31:40,260testlog.ThreadBody.run(TestLog.java:49)Thread-0Thread-0 started!  
  8. 36   WARN  [2012-11-05 14:31:40,263testlog.ThreadBody.run(TestLog.java:49)Thread-3Thread-3 started!  
  9. 38   WARN  [2012-11-05 14:31:40,265testlog.ThreadBody.run(TestLog.java:49)Thread-2Thread-2 started!  
  10. 40   DEBUG [2012-11-05 14:31:40,267testlog.ThreadBody.run(TestLog.java:51)Thread-2this is debug  
  11. 40   INFO  [2012-11-05 14:31:40,267testlog.ThreadBody.run(TestLog.java:52)Thread-2this is info  
  12. 40   WARN  [2012-11-05 14:31:40,267testlog.ThreadBody.run(TestLog.java:53)Thread-2this is warn  
  13. 41   ERROR [2012-11-05 14:31:40,268testlog.ThreadBody.run(TestLog.java:54)Thread-2this is error  
  14. 41   WARN  [2012-11-05 14:31:40,268testlog.ThreadBody.run(TestLog.java:56)Thread-2Thread-2 finished!  
  15. 44   DEBUG [2012-11-05 14:31:40,271testlog.ThreadBody.run(TestLog.java:51)Thread-3this is debug  
  16. 46   INFO  [2012-11-05 14:31:40,273testlog.ThreadBody.run(TestLog.java:52)Thread-3this is info  
  17. 46   WARN  [2012-11-05 14:31:40,273testlog.ThreadBody.run(TestLog.java:53)Thread-3this is warn  
  18. 47   ERROR [2012-11-05 14:31:40,274testlog.ThreadBody.run(TestLog.java:54)Thread-3this is error  
  19. 47   WARN  [2012-11-05 14:31:40,274testlog.ThreadBody.run(TestLog.java:56)Thread-3Thread-3 finished!  
  20. 38   WARN  [2012-11-05 14:31:40,265testlog.ThreadBody.run(TestLog.java:49)Thread-4Thread-4 started!  
  21. 49   DEBUG [2012-11-05 14:31:40,276testlog.ThreadBody.run(TestLog.java:51)Thread-1this is debug  
  22. 50   INFO  [2012-11-05 14:31:40,277testlog.ThreadBody.run(TestLog.java:52)Thread-1this is info  
  23. 50   WARN  [2012-11-05 14:31:40,277testlog.ThreadBody.run(TestLog.java:53)Thread-1this is warn  
  24. 50   ERROR [2012-11-05 14:31:40,277testlog.ThreadBody.run(TestLog.java:54)Thread-1this is error  
  25. 50   WARN  [2012-11-05 14:31:40,277testlog.ThreadBody.run(TestLog.java:56)Thread-1Thread-1 finished!  
  26. 50   DEBUG [2012-11-05 14:31:40,277testlog.ThreadBody.run(TestLog.java:51)Thread-0this is debug  
  27. 50   INFO  [2012-11-05 14:31:40,277testlog.ThreadBody.run(TestLog.java:52)Thread-0this is info  
  28. 50   DEBUG [2012-11-05 14:31:40,277testlog.ThreadBody.run(TestLog.java:51)Thread-4this is debug  
  29. 50   WARN  [2012-11-05 14:31:40,277testlog.ThreadBody.run(TestLog.java:53)Thread-0this is warn  
  30. 51   INFO  [2012-11-05 14:31:40,278testlog.ThreadBody.run(TestLog.java:52)Thread-4this is info  
  31. 51   ERROR [2012-11-05 14:31:40,278testlog.ThreadBody.run(TestLog.java:54)Thread-0this is error  
  32. 51   WARN  [2012-11-05 14:31:40,278testlog.ThreadBody.run(TestLog.java:53)Thread-4this is warn  
  33. 51   ERROR [2012-11-05 14:31:40,278testlog.ThreadBody.run(TestLog.java:54)Thread-4this is error  
  34. 51   WARN  [2012-11-05 14:31:40,278testlog.ThreadBody.run(TestLog.java:56)Thread-0Thread-0 finished!  
  35. 51   WARN  [2012-11-05 14:31:40,278testlog.ThreadBody.run(TestLog.java:56)Thread-4Thread-4 finished!  

 

  同时,log文件夹下出现了main、Thread-0~Thread-4五

log4j.additivity是 子Logger 是否继承 父Logger 的 输出源(appender) 的标志位。具体说,默认情况下 子Logger 会继承 父Logger 的appender,也就是说 子Logger 会在 父Logger 的appender里输出。若是additivity设为false,则 子Logger 只会在自己的appender里输出,而不会在 父Logger 的appender里输出。 

如: 
log4j.rootLogger=INFO, stdout,logfile 
log4j.logger.com.ambow.upgrade=INFO, dataSync 


则com.ambow.upgrade包及其子包下的Logger不光在Appender dataSync里输出,也会在rootLogger的Appender stuout和logfile中输出; 
若想让com.ambow.upgrade包及其子包下的Logger只在Appender dataSync中输出,则在log4j.properties中添加下行即可: 
log4j.additivity.com.ambow.upgrade=false 


 
与此对应的在logback中的配置为:
<logger name="com.apabi.ptvs.web.DataController"
additivity="false">
<level value="INFO" />
<appender-ref ref="logfile" />
</logger>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值