1 package org.apache.log4j; 2 3 18 19 import org.apache.log4j.RollingCalendar; 20 import org.apache.log4j.helpers.OptionConverter; 21 import org.apache.log4j.helpers.QuietWriter; 22 import org.apache.log4j.helpers.CountingQuietWriter; 23 import org.apache.log4j.helpers.LogLog; 24 import org.apache.log4j.spi.LoggingEvent; 25 26 import java.util.Date ; 27 import java.io.IOException ; 28 import java.io.Writer ; 29 import java.text.SimpleDateFormat ; 30 import java.io.File ; 31 import java.io.FilenameFilter ; 32 33 69 public class CompositeRollingAppender extends org.apache.log4j.FileAppender 70 { 71 static final int TOP_OF_TROUBLE=-1; 74 static final int TOP_OF_MINUTE = 0; 75 static final int TOP_OF_HOUR = 1; 76 static final int HALF_DAY = 2; 77 static final int TOP_OF_DAY = 3; 78 static final int TOP_OF_WEEK = 4; 79 static final int TOP_OF_MONTH = 5; 80 81 82 static final int BY_SIZE = 1; 83 static final int BY_DATE = 2; 84 static final int BY_COMPOSITE = 3; 85 86 static final String S_BY_SIZE = "Size"; 88 static final String S_BY_DATE = "Date"; 89 static final String S_BY_COMPOSITE = "Composite"; 90 91 95 private String datePattern = "'.'yyyy-MM-dd"; 96 97 100 private String scheduledFilename = null; 101 102 103 private long nextCheck = System.currentTimeMillis () - 1; 104 105 106 Date now = new Date (); 107 108 SimpleDateFormat sdf; 109 110 111 RollingCalendar rc = new RollingCalendar(); 112 113 114 int checkPeriod = TOP_OF_TROUBLE; 115 116 117 protected long maxFileSize = 10*1024*1024; 118 119 120 protected int maxSizeRollBackups = 0; 121 122 protected int curSizeRollBackups = 0; 123 124 125 protected int maxTimeRollBackups = -1; 126 protected int curTimeRollBackups = 0; 127 128 134 protected int countDirection = -1; 135 136 137 protected int rollingStyle = BY_COMPOSITE; 138 protected boolean rollDate = true; 139 protected boolean rollSize = true; 140 141 148 protected boolean staticLogFileName = true; 149 150 151 protected String baseFileName; 152 153 154 public CompositeRollingAppender() { 155 } 156 157 162 public CompositeRollingAppender (Layout layout, String filename, 163 String datePattern) throws IOException { 164 this(layout, filename, datePattern, true); 165 } 166 167 176 public CompositeRollingAppender(Layout layout, String filename, boolean append) 177 throws IOException { 178 super(layout, filename, append); 179 } 180 181 186 public CompositeRollingAppender (Layout layout, String filename, 187 String datePattern, boolean append) throws IOException { 188 super(layout, filename, append); 189 this.datePattern = datePattern; 190 activateOptions(); 191 } 192 199 public CompositeRollingAppender(Layout layout, String filename) throws IOException { 200 super(layout, filename); 201 } 202 203 208 public void setDatePattern(String pattern) { 209 datePattern = pattern; 210 } 211 212 213 public String getDatePattern() { 214 return datePattern; 215 } 216 217 220 public int getMaxSizeRollBackups() { 221 return maxSizeRollBackups; 222 } 223 224 230 public long getMaximumFileSize() { 231 return maxFileSize; 232 } 233 234 250 public void setMaxSizeRollBackups(int maxBackups) { 251 maxSizeRollBackups = maxBackups; 252 } 253 254 266 public void setMaxFileSize(long maxFileSize) { 267 this.maxFileSize = maxFileSize; 268 } 269 270 282 public void setMaximumFileSize(long maxFileSize) { 283 this.maxFileSize = maxFileSize; 284 } 285 286 297 public void setMaxFileSize(String value) { 298 maxFileSize = OptionConverter.toFileSize(value, maxFileSize + 1); 299 } 300 301 protected void setQWForFiles(Writer writer) { 302 qw = new CountingQuietWriter(writer, errorHandler); 303 } 304 305 int computeCheckPeriod() { 307 RollingCalendar c = new RollingCalendar(); 308 Date epoch = new Date (0); 310 if(datePattern != null) { 311 for(int i = TOP_OF_MINUTE; i <= TOP_OF_MONTH; i++) { 312 String r0 = sdf.format(epoch); 313 c.setType(i); 314 Date next = new Date (c.getNextCheckMillis(epoch)); 315 String r1 = sdf.format(next); 316 if(r0 != null && r1 != null && !r0.equals(r1)) { 318 return i; 319 } 320 } 321 } 322 return TOP_OF_TROUBLE; } 324 325 331 protected void subAppend(LoggingEvent event) { 332 333 if (rollDate) { 334 long n = System.currentTimeMillis(); 335 if (n >= nextCheck) { 336 now.setTime(n); 337 nextCheck = rc.getNextCheckMillis(now); 338 339 rollOverTime(); 340 } 341 } 342 343 if (rollSize) { 344 if ((fileName != null) && ((CountingQuietWriter) qw).getCount() >= maxFileSize) { 345 rollOverSize(); 346 } 347 } 348 349 super.subAppend(event); 350 } 351 352 public void setFile(String file) 353 { 354 baseFileName = file.trim(); 355 fileName = file.trim(); 356 } 357 358 362 public synchronized void setFile(String fileName, boolean append) throws IOException { 363 if (!staticLogFileName) { 364 scheduledFilename = fileName = fileName.trim() + sdf.format(now); 365 if (countDirection > 0) { 366 scheduledFilename = fileName = fileName + '.' + (++curSizeRollBackups); 367 } 368 } 369 370 super.setFile(fileName, append); 371 if(append) { 372 File f = new File (fileName); 373 ((CountingQuietWriter) qw).setCount(f.length()); 374 } 375 } 376 377 public int getCountDirection() { 378 return countDirection; 379 } 380 381 public void setCountDirection(int direction) { 382 countDirection = direction; 383 } 384 385 public int getRollingStyle () { 386 return rollingStyle; 387 } 388 389 public void setRollingStyle(int style) { 390 rollingStyle = style; 391 switch (rollingStyle) { 392 case BY_SIZE: 393 rollDate = false; 394 rollSize = true; 395 break; 396 case BY_DATE: 397 rollDate = true; 398 rollSize = false; 399 break; 400 case BY_COMPOSITE: 401 rollDate = true; 402 rollSize = true; 403 break; 404 default: 405 errorHandler.error("Invalid rolling Style, use 1 (by size only), 2 (by date only) or 3 (both)"); 406 } 407 } 408 409 422 public boolean getStaticLogFileName() { 423 return staticLogFileName; 424 } 425 426 public void setStaticLogFileName(boolean s) { 427 staticLogFileName = s; 428 } 429 430 public void setStaticLogFileName(String value) { 431 setStaticLogFileName(OptionConverter.toBoolean(value, true)); 432 } 433 434 443 protected void existingInit() { 444 445 curSizeRollBackups = 0; 446 curTimeRollBackups = 0; 447 448 String filter; 450 if (staticLogFileName || !rollDate) { 451 filter = baseFileName + ".*"; 452 } 453 else { 454 filter = scheduledFilename + ".*"; 455 } 456 457 File f = new File (baseFileName); 458 f = f.getParentFile(); 459 if (f == null) 460 f = new File ("."); 461 462 LogLog.debug("Searching for existing files in: " + f); 463 String [] files = f.list(); 464 465 if (files != null) { 466 for (int i = 0; i < files.length; i++) { 467 if (!files[i].startsWith(baseFileName)) 468 continue; 469 470 int index = files[i].lastIndexOf("."); 471 472 if (staticLogFileName) { 473 int endLength = files[i].length() - index; 474 if (baseFileName.length() + endLength != files[i].length()) { 475 continue; 477 } 478 } 479 480 try { 481 int backup = Integer.parseInt(files[i].substring(index + 1, files[i].length())); 482 LogLog.debug("From file: " + files[i] + " -> " + backup); 483 if (backup > curSizeRollBackups) 484 curSizeRollBackups = backup; 485 } 486 catch (Exception e) { 487 LogLog.debug("Encountered a backup file not ending in .x " + files[i]); 490 } 491 } 492 } 493 LogLog.debug("curSizeRollBackups starts at: " + curSizeRollBackups); 494 496 498 if (staticLogFileName && rollDate) { 500 File old = new File (baseFileName); 501 if (old.exists()) { 502 Date last = new Date (old.lastModified()); 503 if (!(sdf.format(last).equals(sdf.format(now)))) { 504 scheduledFilename = baseFileName + sdf.format(last); 505 LogLog.debug("Initial roll over to: " + scheduledFilename); 506 rollOverTime(); 507 } 508 } 509 } 510 LogLog.debug("curSizeRollBackups after rollOver at: " + curSizeRollBackups); 511 513 } 514 515 520 public void activateOptions() { 521 522 if(datePattern != null) { 524 now.setTime(System.currentTimeMillis()); 525 sdf = new SimpleDateFormat (datePattern); 526 int type = computeCheckPeriod(); 527 rc.setType(type); 529 nextCheck = rc.getNextCheckMillis(now); 531 } else { 532 if (rollDate) 533 LogLog.error("Either DatePattern or rollingStyle options are not set for ["+ 534 name+"]."); 535 } 536 537 existingInit(); 538 539 super.activateOptions(); 540 541 if (rollDate && fileName != null && scheduledFilename == null) 542 scheduledFilename = fileName + sdf.format(now); 543 } 544 545 549 protected void rollOverTime() { 550 551 curTimeRollBackups++; 552 553 555 if (staticLogFileName) { 556 557 if (datePattern == null) { 558 errorHandler.error("Missing DatePattern option in rollOver()."); 559 return; 560 } 561 562 String dateFormat = sdf.format(now); 566 if (scheduledFilename.equals(fileName + dateFormat)) { 567 errorHandler.error("Compare " + scheduledFilename + " : " + fileName + dateFormat); 568 return; 569 } 570 571 this.closeFile(); 573 574 String from, to; 576 for (int i = 1; i <= curSizeRollBackups; i++) { 577 from = fileName + '.' + i; 578 to = scheduledFilename + '.' + i; 579 rollFile(from, to); 580 } 581 582 rollFile(fileName, scheduledFilename); 583 } 584 585 try { 586 curSizeRollBackups = 0; 590 scheduledFilename = fileName + sdf.format(now); 592 this.setFile(baseFileName, false); 593 } 594 catch(IOException e) { 595 errorHandler.error("setFile("+fileName+", false) call failed."); 596 } 597 598 } 599 600 603 protected static void rollFile(String from, String to) { 604 File target = new File (to); 605 if (target.exists()) { 606 LogLog.debug("deleting existing target file: " + target); 607 target.delete(); 608 } 609 610 File file = new File (from); 611 file.renameTo(target); 612 LogLog.debug(from +" -> "+ to); 613 } 614 615 616 protected static void deleteFile(String fileName) { 617 File file = new File (fileName); 618 if (file.exists()) { 619 file.delete(); 620 } 621 } 622 623 643 644 protected void rollOverSize() { 646 File file; 647 648 this.closeFile(); 650 LogLog.debug("rolling over count=" + ((CountingQuietWriter) qw).getCount()); 651 LogLog.debug("maxSizeRollBackups = " + maxSizeRollBackups); 652 LogLog.debug("curSizeRollBackups = " + curSizeRollBackups); 653 LogLog.debug("countDirection = " + countDirection); 654 655 if (maxSizeRollBackups != 0) { 657 658 if (countDirection < 0) { 659 if (curSizeRollBackups == maxSizeRollBackups) { 661 deleteFile(fileName + '.' + maxSizeRollBackups); 662 curSizeRollBackups--; 663 } 664 665 for (int i = curSizeRollBackups; i >= 1; i--) { 667 rollFile((fileName + "." + i), (fileName + '.' + (i + 1))); 668 } 669 670 curSizeRollBackups++; 671 rollFile(fileName, fileName + ".1"); 673 674 } else if (countDirection == 0) { 676 curSizeRollBackups++; 678 now.setTime(System.currentTimeMillis()); 679 scheduledFilename = fileName + sdf.format(now); 680 rollFile(fileName, scheduledFilename); 681 } 682 else { if (curSizeRollBackups >= maxSizeRollBackups && maxSizeRollBackups > 0) { 684 int oldestFileIndex = curSizeRollBackups - maxSizeRollBackups + 1; 686 deleteFile(fileName + '.' + oldestFileIndex); 687 } 688 689 if (staticLogFileName) { 690 curSizeRollBackups++; 691 rollFile(fileName, fileName + '.' + curSizeRollBackups); 692 } 693 } 694 } 695 696 try { 697 this.setFile(baseFileName, false); 700 } 701 catch(IOException e) { 702 LogLog.error("setFile("+fileName+", false) call failed.", e); 703 } 704 } 705 706 } | Popular Tags |