如何利用Log4j将不同级别,不同package中Log输出到不同的文件中

Log4j对我来说从来就是一笔糊涂账, 基本上就是从其他项目中, 或网上找一段下来依葫芦画瓢,反正都是无关痛痒的东西,从来没有仔细研究过。

最近做了个小项目,客户把Log看的比业务都重要,不得已又要提高自己了,仔细研究了一下,终于从稀里糊涂里走出来了。

本文不打算详细的介绍Log4j, 所以,诸如Log的 level(级别), Appender (输出目的地),Layout(输出格式)以及打印参数等等, 不再熬述, 因为这样的文章网上一搜一麻袋,各位如果想找这方面的资料, 那就Google吧。

本文要说明的重点有两个:

1.如何利用Log4j将不同级别,不同package中Log输出到不同的文件中

2.Log4j的设置和package划分的关系

本文将从实战的角度出发,讲述本项目对Log输出的要求, 以及如何实现这样的要求, 希望对各位童鞋有用。

一.项目简介

环境:Eclipse 

语言:Java

业务:分为Web系 和 Batch系两个模块

Package:

├─x
│  └─y
│      └─z
│          └─e

│              └─w

// 以下为Web系

│                  ├─action
│                  │  └─interceptor
│                  ├─dto
│                  ├─entity
│                  ├─exception
│                  ├─hibernate
│                  ├─listener
│                  ├─service

│                  └─util

// 以下为Batch系

│                  ├─batch
│                  │  ├─bean
│                  │  ├─conf
│                  │  ├─exception
│                  │  ├─query

│                  │  └─util

// 其他

└─template
    └─simple


PS:

从上面的目录结构图不难看出, Web系和Batch系没有明确的分开,Batch系的Source全部在【bacth】package下面了, 但是Web系的Source却没有定义一个独立的package,而是散落在【w】package下面。

这是一个垃圾的设计,由于我一时的疏忽,没有考虑周全造成的。这会给Log4j的配置带来不必要的麻烦。在稍后会讲解它的弊端以及如何改善这个问题。

二.对Log输出的要求

1. 只输出DEBUG,INFO,ERROR三种级别的LOG

2. Web系的LOG分别输出到 web_debug.log, web_info.log, web_error.log 文件中

3. Batch系的LOG分别输出到 batch_debug.log, batch_info.log, batch_error.log 文件中

  PS:注意Web系和Batch系是分开的,也就是说在Batch系的Log中不能出现Web系的Log,Web系的Log也不能出现在Batch系的Log中。

4. 每个Class,Method的预定动作,都会输出设计书规定的Log。

   考虑到Framework采用Struts2 + Hibernate, 所以,Struts和Hibernate输出的Log,在项目发布时,预定关闭。

   但是,要让客户能够轻而易举的将这两个OpenSource的Log打开。

   但是,除此之外的其他第三方的OpenSource输出的Log,一律不准出现在Log文件中。

  PS:客户对Log4j的了解为零(其实他也懂一点,但是他命令我把他当做傻瓜来看,这让我很为难,但我必须服从命令^_^)

// 其他打印格式等信息,此处省略,这不是本文讲述的重点

三.实现

[plain]  view plain copy
  1. #--------------------------------------------------------------------    
  2. #log4j.properties    
  3. #--------------------------------------------------------------------    
  4.     
  5. # log4j.rootLogger = arg1, arg2, arg3,....    
  6. # arg1 = ( DEBUG | INFO | WARN | ERROR | ALL | OFF | FATAL )    
  7. # arg2,... is appender.    
  8. #log4j.rootLogger = ERROR, C0, A0, A1, A2    
  9.     
  10. #In order to facilitate all levels of the log output can be flexible,    
  11. #root logger is closed    
  12. log4j.rootLogger = OFF    
  13.     
  14. #------------------------    
  15. #Web Log    
  16. #Level :    
  17. #   Followed from low to high is : ( DEBUG | INFO | WARN | ERROR | ALL | OFF | FATAL )    
  18. #   Higher than the current level log only will be output.    
  19. #appender :    
  20. #   A0 : web debug log appender    
  21. #   A1 : web info log appender    
  22. #   A2 : web error log appender    
  23. #   C0 : web console log appender, currently is not being used.    
  24. #       if you want to use it, add it at log appender.    
  25. #       for example : log4j.logger.x.y.z.e.w.action = DEBUG, C0, A0, A1, A2    
  26. #       after used it, log information will be output to the console.    
  27. #    
  28. #------------------------    
  29. # system log    
  30. log4j.logger.x.y.z.e.w.action = DEBUG, A0, A1, A2    
  31. log4j.logger.x.y.z.e.w.action.interceptor = DEBUG, A0, A1, A2    
  32. log4j.logger.x.y.z.e.w.bean = DEBUG, A0, A1, A2    
  33. log4j.logger.x.y.z.e.w.dto = DEBUG, A0, A1, A2    
  34. log4j.logger.x.y.z.e.w.entity = DEBUG, A0, A1, A2    
  35. log4j.logger.x.y.z.e.w.exception = DEBUG, A0, A1, A2    
  36. log4j.logger.x.y.z.e.w.hibernate = DEBUG, A0, A1, A2    
  37. log4j.logger.x.y.z.e.w.listener = DEBUG, A0, A1, A2    
  38. log4j.logger.x.y.z.e.w.service = DEBUG, A0, A1, A2    
  39. log4j.logger.x.y.z.e.w.util = DEBUG, A0, A1, A2    
  40.     
  41. #hibernate log    
  42. #hibernate log is closed, if you want to open it, use the following format .    
  43. #log4j.logger.org.hibernate = arg1, arg2    
  44. #arg1 : (DEBUG | INFO | WARN | ERROR | ALL | OFF | FATAL )    
  45. #arg2 : A0, A1, A2    
  46.     
  47. log4j.logger.org.hibernate = OFF    
  48.     
  49. #struts2 log    
  50. #struts log is closed, if you want to open it, use the following format .    
  51. #log4j.logger.org.apache.struts2 = arg1, arg2    
  52. #arg1 : (DEBUG | INFO | WARN | ERROR | ALL | OFF | FATAL )    
  53. #arg2 : A0, A1, A2    
  54.     
  55. log4j.logger.org.apache.struts2 = OFF    
  56.     
  57. #------------------------    
  58. # batch log    
  59. # B0 : batch debug log appender    
  60. # B1 : batch info log appender    
  61. # B2 : batch error log appender    
  62. #------------------------    
  63. #system batch log    
  64. log4j.logger.x.y.z.e.w.batch = DEBUG, B0, B1, B2    
  65.     
  66. #---------------------------------------------------------------------    
  67. # Console    
  68. # console appender is currently not being used, if you use it,     
  69. # log information will be output to the console.    
  70. # How to use it? -> in the corresponding log appender add it.    
  71. # for example : log4j.logger.x.y.z.e.w.action = DEBUG, C0, A0, A1, A2    
  72. log4j.appender.C0 = org.apache.log4j.ConsoleAppender    
  73. log4j.appender.C0.Threshold = ALL    
  74. log4j.appender.C0.layout = org.apache.log4j.PatternLayout    
  75. log4j.appender.C0.layout.ConversionPattern=[%d{HH:mm:ss,SSS}][%-5p] (%F#%M:%L) - %m%n    
  76.     
  77. #---------------------------------------------------------------------    
  78. # WEB DEBUG LOG    
  79. log4j.appender.A0 = a.b.c.log4j.DailyRollingFileAppenderEx    
  80. log4j.appender.A0.File = /var/log/web_debug.log    
  81. log4j.appender.A0.Threshold = DEBUG    
  82. log4j.appender.A0.append=true    
  83. log4j.appender.A0.layout = org.apache.log4j.PatternLayout    
  84. log4j.appender.A0.layout.ConversionPattern=[%d{HH:mm:ss,SSS}][%-5p] (%F#%M:%L) - %m%n    
  85.     
  86. #---------------------------------------------------------------------    
  87. # WEB INFO LOG    
  88. log4j.appender.A1 = a.b.c.log4j.DailyRollingFileAppenderEx    
  89. log4j.appender.A1.File = /var/log/web_info.log    
  90. log4j.appender.A1.Threshold = INFO    
  91. log4j.appender.A1.append=true    
  92. log4j.appender.A1.layout = org.apache.log4j.PatternLayout    
  93. log4j.appender.A1.layout.ConversionPattern=[%d{HH:mm:ss,SSS}][%-5p] (%F#%M:%L) - %m%n    
  94.     
  95. #---------------------------------------------------------------------    
  96. # WEB ERROR LOG    
  97. log4j.appender.A2 = a.b.c.log4j.DailyRollingFileAppenderEx    
  98. log4j.appender.A2.File = /var/log/web_error.log    
  99. log4j.appender.A2.Threshold = ERROR    
  100. log4j.appender.A2.append=true    
  101. log4j.appender.A2.layout = org.apache.log4j.PatternLayout    
  102. log4j.appender.A2.layout.ConversionPattern=[%d{HH:mm:ss,SSS}][%-5p] (%F#%M:%L) - %m%n    
  103.     
  104. #---------------------------------------------------------------------    
  105. # BATCH DEBUG LOG    
  106. log4j.appender.B0 = a.b.c.log4j.DailyRollingFileAppenderEx    
  107. log4j.appender.B0.File = /var/log/batch_debug.log    
  108. log4j.appender.B0.Threshold = DEBUG    
  109. log4j.appender.B0.append=true    
  110. log4j.appender.B0.layout = org.apache.log4j.PatternLayout    
  111. log4j.appender.B0.layout.ConversionPattern=[%d{HH:mm:ss,SSS}][%-5p] (%F#%M:%L) - %m%n    
  112.     
  113. #---------------------------------------------------------------------    
  114. # BATCH INFO LOG    
  115. log4j.appender.B1 = a.b.c.log4j.DailyRollingFileAppenderEx    
  116. log4j.appender.B1.File = /var/log/batch_info.log    
  117. log4j.appender.B1.Threshold = INFO    
  118. log4j.appender.B1.append=true    
  119. log4j.appender.B1.layout = org.apache.log4j.PatternLayout    
  120. log4j.appender.B1.layout.ConversionPattern=[%d{HH:mm:ss,SSS}][%-5p] (%F#%M:%L) - %m%n    
  121.     
  122. #---------------------------------------------------------------------    
  123. # BATCH ERROR LOG    
  124. log4j.appender.B2 = a.b.c.log4j.DailyRollingFileAppenderEx    
  125. log4j.appender.B2.File = /var/log/batch_error.log    
  126. log4j.appender.B2.Threshold = ERROR    
  127. log4j.appender.B2.append=true    
  128. log4j.appender.B2.layout = org.apache.log4j.PatternLayout    
  129. log4j.appender.B2.layout.ConversionPattern=[%d{HH:mm:ss,SSS}][%-5p] (%F#%M:%L) - %m%n    


这里对Log4j的设置做一下讲解:

讲解一. 第12行 

[plain]  view plain copy
  1. log4j.rootLogger = OFF  

为什么将根Log关闭了呢? 因为所有的logger都会自动继承RootLogger,客户要求除Struts和Hibernate外的其他第三方OpenSource输出的Log,一律不准输出。
项目中使用了大量的其他第三方的OpenSource,RootLogger设定为OFF,所有使用Log4j的OpenSource都会自动继承RootLogger,被设定OFF。

除非再次显式的为它指定logger,否则,所有使用Log4j输出的Log都将不会输出,本项目中,在关闭RootLogger以后,就再次显式的指定了以下logger。

[plain]  view plain copy
  1. log4j.logger.x.y.z.e.w.action = DEBUG, A0, A1, A2  
  2. log4j.logger.x.y.z.e.w.action.interceptor = DEBUG, A0, A1, A2  
  3. log4j.logger.x.y.z.e.w.bean = DEBUG, A0, A1, A2  
  4. log4j.logger.x.y.z.e.w.dto = DEBUG, A0, A1, A2  
  5. log4j.logger.x.y.z.e.w.entity = DEBUG, A0, A1, A2  
  6. log4j.logger.x.y.z.e.w.exception = DEBUG, A0, A1, A2  
  7. log4j.logger.x.y.z.e.w.hibernate = DEBUG, A0, A1, A2  
  8. log4j.logger.x.y.z.e.w.listener = DEBUG, A0, A1, A2  
  9. log4j.logger.x.y.z.e.w.service = DEBUG, A0, A1, A2  
  10. log4j.logger.x.y.z.e.w.util = DEBUG, A0, A1, A2  

[plain]  view plain copy
  1. log4j.logger.x.y.z.e.w.batch = DEBUG, B0, B1, B2  

这样一来,除上面明确指出的logger以外,其他所有的log都不会输出了。

当然还有下面两个Log:

[plain]  view plain copy
  1. #hibernate log  
  2. #hibernate log is closed, if you want to open it, use the following format .  
  3. #log4j.logger.org.hibernate = arg1, arg2  
  4. #arg1 : (DEBUG | INFO | WARN | ERROR | ALL | OFF | FATAL )  
  5. #arg2 : A0, A1, A2  
  6.   
  7.   
  8. log4j.logger.org.hibernate = OFF  
  9.   
  10.   
  11. #struts2 log  
  12. #struts log is closed, if you want to open it, use the following format .  
  13. #log4j.logger.org.apache.struts2 = arg1, arg2  
  14. #arg1 : (DEBUG | INFO | WARN | ERROR | ALL | OFF | FATAL )  
  15. #arg2 : A0, A1, A2  
  16.   
  17.   
  18. log4j.logger.org.apache.struts2 = OFF  

这两个不写,也不会输出Log,因为他们会继承自RootLogger的OFF设定。

上面说了,客户要求预定将这两个Log关闭,必要的时候可以打开。看到上面蹩脚的英文说明没有,那是本人一级英语的杰作。尽管看上去都是废话,没办法,客户命令我把他当做傻瓜来看待。

讲解二.package 的划分与Log4j设置的关系

[plain]  view plain copy
  1. # system log  
  2. log4j.logger.x.y.z.e.w.action = DEBUG, A0, A1, A2  
  3. log4j.logger.x.y.z.e.w.action.interceptor = DEBUG, A0, A1, A2  
  4. log4j.logger.x.y.z.e.w.bean = DEBUG, A0, A1, A2  
  5. log4j.logger.x.y.z.e.w.dto = DEBUG, A0, A1, A2  
  6. log4j.logger.x.y.z.e.w.entity = DEBUG, A0, A1, A2  
  7. log4j.logger.x.y.z.e.w.exception = DEBUG, A0, A1, A2  
  8. log4j.logger.x.y.z.e.w.hibernate = DEBUG, A0, A1, A2  
  9. log4j.logger.x.y.z.e.w.listener = DEBUG, A0, A1, A2  
  10. log4j.logger.x.y.z.e.w.service = DEBUG, A0, A1, A2  
  11. log4j.logger.x.y.z.e.w.util = DEBUG, A0, A1, A2  

这一堆都是对Web系Log输出的控制,精确到了每一个package,没办法,我前面说过了,这个项目中对Web系package的划分是个垃圾的设计,因为他没有将Web系和Batch系的Source完全的分离开来, Web系的Source散落在package【w】下面,而RootLogger又被设定OFF,所以只能这样一个一个的设置了。

那么Web系的package改如何划分才对呢?很简单,只要在package【x.y.z.e.w】的下面再加入一层package,变为【x.y.z.e.w.web】就行了。

这样一来,Web系的package就全部在【x.y.z.e.w.web】的下面了,而Batch系的package已经在【x.y.z.e.w.batch】中了,上面那一堆对Web系Log的设置就可以改成这样了:

[plain]  view plain copy
  1. # system log  
  2. log4j.logger.x.y.z.e.w.web = DEBUG, A0, A1, A2  

是不是简单多了!

好了,这篇文章就写到这里,希望能对童鞋们有所帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值