All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.log4j.RollingFileAppender Maven / Gradle / Ivy

There is a newer version: 1.2.25
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.log4j;

import java.io.IOException;
import java.io.Writer;
import java.io.File;
import java.io.InterruptedIOException;

import org.apache.log4j.helpers.OptionConverter;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.helpers.CountingQuietWriter;
import org.apache.log4j.spi.LoggingEvent;

/**
 * RollingFileAppender extends FileAppender to backup the log files when they
 * reach a certain size.
 * 
 * The log4j extras companion includes alternatives which should be considered
 * for new deployments and which are discussed in the documentation for
 * org.apache.log4j.rolling.RollingFileAppender.
 * 
 * 
 * @author Heinz Richter
 * @author Ceki Gülcü
 * 
 */
public class RollingFileAppender extends FileAppender {

    /**
     * The default maximum file size is 10MB.
     */
    protected long maxFileSize = 10 * 1024 * 1024;

    /**
     * There is one backup file by default.
     */
    protected int maxBackupIndex = 1;

    private long nextRollover = 0;

    /**
     * The default constructor simply calls its {@link FileAppender#FileAppender
     * parents constructor}.
     */
    public RollingFileAppender() {
	super();
    }

    /**
     * Instantiate a RollingFileAppender and open the file designated by
     * filename. The opened filename will become the ouput destination
     * for this appender.
     * 
     * 

* If the append parameter is true, the file will be appended to. * Otherwise, the file desginated by filename will be truncated * before being opened. */ public RollingFileAppender(Layout layout, String filename, boolean append) throws IOException { super(layout, filename, append); } /** * Instantiate a FileAppender and open the file designated by * filename. The opened filename will become the output destination * for this appender. * *

* The file will be appended to. */ public RollingFileAppender(Layout layout, String filename) throws IOException { super(layout, filename); } /** * Returns the value of the MaxBackupIndex option. */ public int getMaxBackupIndex() { return maxBackupIndex; } /** * Get the maximum size that the output file is allowed to reach before being * rolled over to backup files. * * @since 1.1 */ public long getMaximumFileSize() { return maxFileSize; } /** * Implements the usual roll over behaviour. * *

* If MaxBackupIndex is positive, then files {File.1, * ..., File.MaxBackupIndex -1} are renamed to * {File.2, ..., File.MaxBackupIndex}. Moreover, * File is renamed File.1 and closed. A new * File is created to receive further log output. * *

* If MaxBackupIndex is equal to zero, then the File * is truncated with no backup files created. * */ public // synchronization not necessary since doAppend is alreasy synched void rollOver() { File target; File file; if (qw != null) { long size = ((CountingQuietWriter) qw).getCount(); LogLog.debug("rolling over count=" + size); // if operation fails, do not roll again until // maxFileSize more bytes are written nextRollover = size + maxFileSize; } LogLog.debug("maxBackupIndex=" + maxBackupIndex); boolean renameSucceeded = true; // If maxBackups <= 0, then there is no file renaming to be done. if (maxBackupIndex > 0) { // Delete the oldest file, to keep Windows happy. file = new File(fileName + '.' + maxBackupIndex); if (file.exists()) renameSucceeded = file.delete(); // Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3, 2} for (int i = maxBackupIndex - 1; i >= 1 && renameSucceeded; i--) { file = new File(fileName + "." + i); if (file.exists()) { target = new File(fileName + '.' + (i + 1)); LogLog.debug("Renaming file " + file + " to " + target); renameSucceeded = file.renameTo(target); } } if (renameSucceeded) { // Rename fileName to fileName.1 target = new File(fileName + "." + 1); this.closeFile(); // keep windows happy. file = new File(fileName); LogLog.debug("Renaming file " + file + " to " + target); renameSucceeded = file.renameTo(target); // // if file rename failed, reopen file with append = true // if (!renameSucceeded) { try { this.setFile(fileName, true, bufferedIO, bufferSize); } catch (IOException e) { if (e instanceof InterruptedIOException) { Thread.currentThread().interrupt(); } LogLog.error("setFile(" + fileName + ", true) call failed.", e); } } } } // // if all renames were successful, then // if (renameSucceeded) { try { // This will also close the file. This is OK since multiple // close operations are safe. this.setFile(fileName, false, bufferedIO, bufferSize); nextRollover = 0; } catch (IOException e) { if (e instanceof InterruptedIOException) { Thread.currentThread().interrupt(); } LogLog.error("setFile(" + fileName + ", false) call failed.", e); } } } public synchronized void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize) throws IOException { super.setFile(fileName, append, this.bufferedIO, this.bufferSize); if (append) { File f = new File(fileName); ((CountingQuietWriter) qw).setCount(f.length()); } } /** * Set the maximum number of backup files to keep around. * *

* The MaxBackupIndex option determines how many backup files are kept * before the oldest is erased. This option takes a positive integer value. If * set to zero, then there will be no backup files and the log file will be * truncated when it reaches MaxFileSize. */ public void setMaxBackupIndex(int maxBackups) { this.maxBackupIndex = maxBackups; } /** * Set the maximum size that the output file is allowed to reach before being * rolled over to backup files. * *

* This method is equivalent to {@link #setMaxFileSize} except that it is * required for differentiating the setter taking a long argument * from the setter taking a String argument by the JavaBeans * {@link java.beans.Introspector Introspector}. * * @see #setMaxFileSize(String) */ public void setMaximumFileSize(long maxFileSize) { this.maxFileSize = maxFileSize; } /** * Set the maximum size that the output file is allowed to reach before being * rolled over to backup files. * *

* In configuration files, the MaxFileSize option takes an long integer * in the range 0 - 2^63. You can specify the value with the suffixes "KB", "MB" * or "GB" so that the integer is interpreted being expressed respectively in * kilobytes, megabytes or gigabytes. For example, the value "10KB" will be * interpreted as 10240. */ public void setMaxFileSize(String value) { maxFileSize = OptionConverter.toFileSize(value, maxFileSize + 1); } protected void setQWForFiles(Writer writer) { this.qw = new CountingQuietWriter(writer, errorHandler); } /** * This method differentiates RollingFileAppender from its super class. * * @since 0.9.0 */ protected void subAppend(LoggingEvent event) { super.subAppend(event); if (fileName != null && qw != null) { long size = ((CountingQuietWriter) qw).getCount(); if (size >= maxFileSize && size >= nextRollover) { rollOver(); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy