40cc685ef23e925144fbe31795b3e14ddc6836c5.svn-base 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. package org.apache.log4j;
  2. import java.text.*;
  3. import java.io.*;
  4. import org.apache.log4j.helpers.*;
  5. import java.util.*;
  6. import java.util.zip.GZIPOutputStream;
  7. import org.apache.log4j.spi.*;
  8. /**
  9. * 替换log4j包里的DailyRollingFileAppender类,
  10. * 增加文件压缩流程,
  11. * @author xu.zhou
  12. * @date 20211108
  13. */
  14. public class CompressDailyRollingFileAppender extends FileAppender
  15. {
  16. static final int TOP_OF_TROUBLE = -1;
  17. static final int TOP_OF_MINUTE = 0;
  18. static final int TOP_OF_HOUR = 1;
  19. static final int HALF_DAY = 2;
  20. static final int TOP_OF_DAY = 3;
  21. static final int TOP_OF_WEEK = 4;
  22. static final int TOP_OF_MONTH = 5;
  23. private String datePattern;
  24. private String scheduledFilename;
  25. private long nextCheck;
  26. Date now;
  27. SimpleDateFormat sdf;
  28. RollingCalendar rc;
  29. int checkPeriod;
  30. static final TimeZone gmtTimeZone;
  31. public CompressDailyRollingFileAppender() {
  32. this.datePattern = "'.'yyyy-MM-dd";
  33. this.nextCheck = System.currentTimeMillis() - 1L;
  34. this.now = new Date();
  35. this.rc = new RollingCalendar();
  36. this.checkPeriod = -1;
  37. }
  38. public CompressDailyRollingFileAppender(final Layout layout, final String filename, final String datePattern) throws IOException {
  39. super(layout, filename, true);
  40. this.datePattern = "'.'yyyy-MM-dd";
  41. this.nextCheck = System.currentTimeMillis() - 1L;
  42. this.now = new Date();
  43. this.rc = new RollingCalendar();
  44. this.checkPeriod = -1;
  45. this.datePattern = datePattern;
  46. this.activateOptions();
  47. }
  48. public void setDatePattern(final String pattern) {
  49. this.datePattern = pattern;
  50. }
  51. public String getDatePattern() {
  52. return this.datePattern;
  53. }
  54. public void activateOptions() {
  55. super.activateOptions();
  56. if (this.datePattern != null && super.fileName != null) {
  57. this.now.setTime(System.currentTimeMillis());
  58. this.sdf = new SimpleDateFormat(this.datePattern);
  59. final int type = this.computeCheckPeriod();
  60. this.printPeriodicity(type);
  61. this.rc.setType(type);
  62. final File file = new File(super.fileName);
  63. this.scheduledFilename = super.fileName + this.sdf.format(new Date(file.lastModified()));
  64. }
  65. else {
  66. LogLog.error("Either File or DatePattern options are not set for appender [" + super.name + "].");
  67. }
  68. }
  69. void printPeriodicity(final int type) {
  70. switch (type) {
  71. case 0: {
  72. LogLog.debug("Appender [" + super.name + "] to be rolled every minute.");
  73. break;
  74. }
  75. case 1: {
  76. LogLog.debug("Appender [" + super.name + "] to be rolled on top of every hour.");
  77. break;
  78. }
  79. case 2: {
  80. LogLog.debug("Appender [" + super.name + "] to be rolled at midday and midnight.");
  81. break;
  82. }
  83. case 3: {
  84. LogLog.debug("Appender [" + super.name + "] to be rolled at midnight.");
  85. break;
  86. }
  87. case 4: {
  88. LogLog.debug("Appender [" + super.name + "] to be rolled at start of week.");
  89. break;
  90. }
  91. case 5: {
  92. LogLog.debug("Appender [" + super.name + "] to be rolled at start of every month.");
  93. break;
  94. }
  95. default: {
  96. LogLog.warn("Unknown periodicity for appender [" + super.name + "].");
  97. break;
  98. }
  99. }
  100. }
  101. int computeCheckPeriod() {
  102. final RollingCalendar rollingCalendar = new RollingCalendar(CompressDailyRollingFileAppender.gmtTimeZone, Locale.ENGLISH);
  103. final Date epoch = new Date(0L);
  104. if (this.datePattern != null) {
  105. for (int i = 0; i <= 5; ++i) {
  106. final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(this.datePattern);
  107. simpleDateFormat.setTimeZone(CompressDailyRollingFileAppender.gmtTimeZone);
  108. final String r0 = simpleDateFormat.format(epoch);
  109. rollingCalendar.setType(i);
  110. final Date next = new Date(rollingCalendar.getNextCheckMillis(epoch));
  111. final String r2 = simpleDateFormat.format(next);
  112. if (r0 != null && r2 != null && !r0.equals(r2)) {
  113. return i;
  114. }
  115. }
  116. }
  117. return -1;
  118. }
  119. /**
  120. * 日志滚动
  121. * @throws IOException
  122. */
  123. void rollOver() throws IOException {
  124. if (this.datePattern == null) {
  125. super.errorHandler.error("Missing DatePattern option in rollOver().");
  126. return;
  127. }
  128. String dateStr = this.sdf.format(this.now);
  129. final String datedFilename = super.fileName + dateStr;
  130. //要删除的文件是否与最后的日志文件相同,说明此文件还不要处理,正在写入
  131. if (this.scheduledFilename.equals(datedFilename)) {
  132. return;
  133. }
  134. this.closeFile();
  135. //生成要滚动的文件
  136. final File target = new File(this.scheduledFilename);
  137. if (target.exists()) {
  138. //System.out.println("删除文件=>"+target.getName());
  139. target.delete();
  140. }
  141. //System.out.println("datePattern=>"+datePattern);
  142. //System.out.println("datedFilename=>"+datedFilename);
  143. //System.out.println("scheduledFilename=>"+this.scheduledFilename);
  144. //System.out.println("super.fileName=>"+super.fileName);
  145. final File file = new File(super.fileName);
  146. //把正在写入的日志文件更名为带日期的日志文件
  147. final boolean result = file.renameTo(target);
  148. if (result) {
  149. LogLog.debug(super.fileName + " -> " + this.scheduledFilename);
  150. }
  151. else {
  152. LogLog.error("Failed to rename [" + super.fileName + "] to [" + this.scheduledFilename + "].");
  153. }
  154. try {
  155. this.setFile(super.fileName, false, super.bufferedIO, super.bufferSize);
  156. }
  157. catch (IOException e) {
  158. super.errorHandler.error("setFile(" + super.fileName + ", false) call failed.");
  159. }
  160. //压缩日志后删除文件
  161. zipfile(this.scheduledFilename);
  162. this.scheduledFilename = datedFilename;
  163. }
  164. /**
  165. * 压缩日志后删除文件
  166. * @param fileName
  167. */
  168. private void zipfile(String fileName){
  169. //System.out.println("zipfile.fileName========================"+fileName);
  170. File file = new File(fileName);
  171. //creat zip output stream to build zip file
  172. GZIPOutputStream gzout = null;
  173. FileInputStream fin = null;
  174. byte[] buf = new byte[1024];
  175. //file -> gz
  176. try {
  177. fin = new FileInputStream(file);
  178. gzout = new GZIPOutputStream(new FileOutputStream(fileName + ".gz"));
  179. int num;
  180. while ((num = fin.read(buf, 0, buf.length)) != -1) {
  181. gzout.write(buf, 0, num);
  182. }
  183. gzout.flush();
  184. gzout.finish();
  185. LogLog.debug(fileName + " -> " + fileName + ".gz" + " successful!");
  186. } catch (IOException e) {
  187. LogLog.error("add gz file(" + fileName + ".gz" + ") failed.");
  188. } finally {
  189. try {
  190. if (gzout != null) {
  191. gzout.close();
  192. }
  193. if (fin != null)
  194. fin.close();
  195. } catch (IOException e) {
  196. LogLog.error("close Stream failed");
  197. }
  198. }
  199. //delete old file
  200. file.delete();
  201. }
  202. protected void subAppend(final LoggingEvent event) {
  203. final long n = System.currentTimeMillis();
  204. if (n >= this.nextCheck) {
  205. this.now.setTime(n);
  206. this.nextCheck = this.rc.getNextCheckMillis(this.now);
  207. try {
  208. this.rollOver();
  209. }
  210. catch (IOException ioe) {
  211. LogLog.error("rollOver() failed.", ioe);
  212. }
  213. }
  214. super.subAppend(event);
  215. }
  216. static {
  217. gmtTimeZone = TimeZone.getTimeZone("GMT");
  218. }
  219. }