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

ch.qos.logback.core.rolling.RollingFileAppender Maven / Gradle / Ivy

There is a newer version: 2.12.15
Show newest version
/**
 * Logback: the reliable, generic, fast and flexible logging framework.
 * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
 *
 * This program and the accompanying materials are dual-licensed under
 * either the terms of the Eclipse Public License v1.0 as published by
 * the Eclipse Foundation
 *
 *   or (per the licensee's choosing)
 *
 * under the terms of the GNU Lesser General Public License version 2.1
 * as published by the Free Software Foundation.
 */
package ch.qos.logback.core.rolling;

import static ch.qos.logback.core.CoreConstants.CODES_URL;
import static ch.qos.logback.core.CoreConstants.MORE_INFO_PREFIX;

import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;

import ch.qos.logback.core.CoreConstants;
import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.rolling.helper.CompressionMode;
import ch.qos.logback.core.rolling.helper.FileNamePattern;
import ch.qos.logback.core.util.ContextUtil;

/**
 * RollingFileAppender extends {@link FileAppender} to backup the
 * log files depending on {@link RollingPolicy} and {@link TriggeringPolicy}.
 * 

*

* For more information about this appender, please refer to the online manual * at http://logback.qos.ch/manual/appenders.html#RollingFileAppender * * @author Heinz Richter * @author Ceki Gülcü */ public class RollingFileAppender extends FileAppender { File currentlyActiveFile; TriggeringPolicy triggeringPolicy; RollingPolicy rollingPolicy; static private String RFA_NO_TP_URL = CODES_URL + "#rfa_no_tp"; static private String RFA_NO_RP_URL = CODES_URL + "#rfa_no_rp"; static private String COLLISION_URL = CODES_URL + "#rfa_collision"; static private String RFA_LATE_FILE_URL = CODES_URL + "#rfa_file_after"; public void start() { if (triggeringPolicy == null) { addWarn("No TriggeringPolicy was set for the RollingFileAppender named " + getName()); addWarn(MORE_INFO_PREFIX + RFA_NO_TP_URL); return; } if (!triggeringPolicy.isStarted()) { addWarn("TriggeringPolicy has not started. RollingFileAppender will not start"); return; } if (checkForCollisionsInPreviousRollingFileAppenders()) { addError("Collisions detected with FileAppender/RollingAppender instances defined earlier. Aborting."); addError(MORE_INFO_PREFIX + COLLISION_WITH_EARLIER_APPENDER_URL); return; } // we don't want to void existing log files if (!append) { addWarn("Append mode is mandatory for RollingFileAppender. Defaulting to append=true."); append = true; } if (rollingPolicy == null) { addError("No RollingPolicy was set for the RollingFileAppender named " + getName()); addError(MORE_INFO_PREFIX + RFA_NO_RP_URL); return; } // sanity check for http://jira.qos.ch/browse/LOGBACK-796 if (checkForFileAndPatternCollisions()) { addError("File property collides with fileNamePattern. Aborting."); addError(MORE_INFO_PREFIX + COLLISION_URL); return; } if (isPrudent()) { if (rawFileProperty() != null) { addWarn("Setting \"File\" property to null on account of prudent mode"); setFile(null); } if (rollingPolicy.getCompressionMode() != CompressionMode.NONE) { addError("Compression is not supported in prudent mode. Aborting"); return; } } currentlyActiveFile = new File(getFile()); addInfo("Active log file name: " + getFile()); super.start(); } private boolean checkForFileAndPatternCollisions() { if (triggeringPolicy instanceof RollingPolicyBase) { final RollingPolicyBase base = (RollingPolicyBase) triggeringPolicy; final FileNamePattern fileNamePattern = base.fileNamePattern; // no use checking if either fileName or fileNamePattern are null if (fileNamePattern != null && fileName != null) { String regex = fileNamePattern.toRegex(); return fileName.matches(regex); } } return false; } private boolean checkForCollisionsInPreviousRollingFileAppenders() { boolean collisionResult = false; if (triggeringPolicy instanceof RollingPolicyBase) { final RollingPolicyBase base = (RollingPolicyBase) triggeringPolicy; final FileNamePattern fileNamePattern = base.fileNamePattern; boolean collisionsDetected = innerCheckForFileNamePatternCollisionInPreviousRFA(fileNamePattern); if (collisionsDetected) collisionResult = true; } return collisionResult; } private boolean innerCheckForFileNamePatternCollisionInPreviousRFA(FileNamePattern fileNamePattern) { boolean collisionsDetected = false; @SuppressWarnings("unchecked") Map map = (Map) context.getObject(CoreConstants.RFA_FILENAME_PATTERN_COLLISION_MAP); if (map == null) { return collisionsDetected; } for (Entry entry : map.entrySet()) { if (fileNamePattern.equals(entry.getValue())) { addErrorForCollision("FileNamePattern", entry.getValue().toString(), entry.getKey()); collisionsDetected = true; } } if (name != null) { map.put(getName(), fileNamePattern); } return collisionsDetected; } @Override public void stop() { super.stop(); if (rollingPolicy != null) rollingPolicy.stop(); if (triggeringPolicy != null) triggeringPolicy.stop(); Map map = ContextUtil.getFilenamePatternCollisionMap(context); if (map != null && getName() != null) map.remove(getName()); } @Override public void setFile(String file) { // http://jira.qos.ch/browse/LBCORE-94 // allow setting the file name to null if mandated by prudent mode if (file != null && ((triggeringPolicy != null) || (rollingPolicy != null))) { addError("File property must be set before any triggeringPolicy or rollingPolicy properties"); addError(MORE_INFO_PREFIX + RFA_LATE_FILE_URL); } super.setFile(file); } @Override public String getFile() { return rollingPolicy.getActiveFileName(); } /** * Implemented by delegating most of the rollover work to a rolling policy. */ public void rollover() { lock.lock(); try { // Note: This method needs to be synchronized because it needs exclusive // access while it closes and then re-opens the target file. // // make sure to close the hereto active log file! Renaming under windows // does not work for open files. this.closeOutputStream(); attemptRollover(); attemptOpenFile(); } finally { lock.unlock(); } } private void attemptOpenFile() { try { // update the currentlyActiveFile LOGBACK-64 currentlyActiveFile = new File(rollingPolicy.getActiveFileName()); // This will also close the file. This is OK since multiple close operations are safe. this.openFile(rollingPolicy.getActiveFileName()); } catch (IOException e) { addError("setFile(" + fileName + ", false) call failed.", e); } } private void attemptRollover() { try { rollingPolicy.rollover(); } catch (RolloverFailure rf) { addWarn("RolloverFailure occurred. Deferring roll-over."); // we failed to roll-over, let us not truncate and risk data loss this.append = true; } } /** * This method differentiates RollingFileAppender from its super class. */ @Override protected void subAppend(E event) { // The roll-over check must precede actual writing. This is the // only correct behavior for time driven triggers. // We need to synchronize on triggeringPolicy so that only one rollover // occurs at a time synchronized (triggeringPolicy) { if (triggeringPolicy.isTriggeringEvent(currentlyActiveFile, event)) { rollover(); } } super.subAppend(event); } public RollingPolicy getRollingPolicy() { return rollingPolicy; } public TriggeringPolicy getTriggeringPolicy() { return triggeringPolicy; } /** * Sets the rolling policy. In case the 'policy' argument also implements * {@link TriggeringPolicy}, then the triggering policy for this appender is * automatically set to be the policy argument. * * @param policy */ @SuppressWarnings("unchecked") public void setRollingPolicy(RollingPolicy policy) { rollingPolicy = policy; if (rollingPolicy instanceof TriggeringPolicy) { triggeringPolicy = (TriggeringPolicy) policy; } } public void setTriggeringPolicy(TriggeringPolicy policy) { triggeringPolicy = policy; if (policy instanceof RollingPolicy) { rollingPolicy = (RollingPolicy) policy; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy