Log4j Un fichier par jour dont le nom inclue la date de création

Voici un petit tutoriel pour créer un fichier de logs par jour incluant la date de création dans le nom du fichier, et cela sans utiliser la classe DailyRollingFileAppender de Log4j (qui selon certaine personne ne fonctionnerais pas toujours correctement).

Ce que je vous propose est un mixe entre deux tutoriels/API  :

Le premier m’a permis de voir comment nommer un fichier de log selon un pattern définie dans un fichier de configuration en étendant une classe de Log4j.
Le second lui offre une façon de créer un fichier par jours.
Je vous invite à voir ces deux sources fortement intéressantes.

Comment fonctionne le mixage réalisé ?

Contrairement à DailyRollingFileAppender, qui lui créer un fichier « nomDuFichier.log » et le renomme à minuit en « nomDuFichier.yyyy-MM-dd.log », ce système inclut la date de création du fichier de log à son nom. Cela permet d’éviter les éventuels problèmes lors du renommage du fichier.
Autre avantage, différents fichiers de logs peuvent être créé tout au long d’une journée. Si vous voulez un fichier toutes les minutes (voir secondes…), vous pouvez. En effet ce système se base sur le pattern de date que vous allez configurer. Par défaut celui-ci est « yyyy-MM-dd ».
Donc dés que la date inclut au nom du fichier est différentes de la date à laquelle une demande d’écriture de log est faite, un nouveau fichier est créé.

Voici la configuration de log4j se trouvant dans un fichier de properties :

log4j.appender.myfunkyappenderlog=fr.waldo.log4j.appender.DatedRollingFileAppender
log4j.appender.myfunkyappenderlog.File=logs/%date%_Funky.log
log4j.appender.myfunkyappenderlog.DatePattern=yyyy_MM_dd_mm # ici un nouveau fichier toutes les minutes
log4j.appender.myfunkyappenderlog.layout=org.apache.log4j.PatternLayout
log4j.appender.myfunkyappenderlog.layout.ConversionPattern=%d{ABSOLUTE} %5p [%c{1}:%L]  %m%n

log4j.logger.myfunkylog =DEBUG, myfunkyappenderlog

La class DatedRollingFileAppender :

package fr.waldo.log4j.appender;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.log4j.FileAppender;
import org.apache.log4j.spi.LoggingEvent;

/**
 * Permet de créer un fichier de log à chaque changement dans le pattern de date définie
 *
 */
public class DatedRollingFileAppender extends FileAppender {

	/**
	 * Datepattern
	 */
	private String datePattern = "yyyy-MM-dd";

	/**
	 * Date in use for the actual logs file
	 */
	private String dateFileInUse = null;

	/**
	 * The file pattern name
	 */
	private String logFileName = "%date%_logs.log";

	public DatedRollingFileAppender() {}

	public String getDatePattern() {
		return datePattern;
	}

	/**
	 * Set Date pattern
	 * This date pattern is used to define the time interval between two log
	 * Le pattern de la date est aussi utilisé pour définir l'interval de temps entre chaque création de fichier de log
	 *
	 * <i>Exemple</i>
	 * <ul><li>
	 * datePattern = yyyy-MM-dd<br />
	 * <br />
	 * actualDate = 2010-12-01 // the date of today<br />
	 * dateFileInUse 2010-12-01 // creation date of the log file<br />
	 * <br />
	 * actualDate == dateFileInUse -> no file is created<br /><br />
	 *
	 * </li>
	 * <li>
	 * datePattern = yyyy-MM-dd<br />
	 * <br />
	 * actualDate = 2010-12-02 // the date of today<br />
	 * dateFileInUse 2010-12-01 // creation date of the log file<br />
	 * <br />
	 * actualDate != dateFileInUse -> file is created with the actualDate
	 * </li>
	 * </ul>
	 *
	 * @param datePattern
	 */
	public void setDatePattern(String datePattern) {
		this.datePattern = datePattern;
	}

	/**
	 * Return the file pattern.
	 */
	public String getFile() {
		return logFileName;
	}

	/**
	 * Set the file paterne name.
	 * %date% will be replace with the current date
	 *
	 * @param logs file name pattern
	 */
	public void setFile(String fileName) {

		logFileName = fileName;

		makeNewFileLog();
	}

	/**
	 * Called by AppenderSkeleton.doAppend() to write a log message formatted
	 * according to the layout defined for this appender.
	 */
	public void append(LoggingEvent event) {

		if(this.layout == null) {
			errorHandler.error("No layout set for the appender named ["+ name+"].");
			return;
		}

		// va créer ou non un nouveau fichier de log
		makeNewFileLog();

		if(this.qw == null) { // should never happen
			errorHandler.error("No output stream or file set for the appender named [" + name + "].");
			return;
		}

		subAppend(event);
	}

	/**
	 * Va créer ou non un nouveau fichier de log
	 */
	private void makeNewFileLog() {

		SimpleDateFormat sdf = new SimpleDateFormat(datePattern);

		String strDate = sdf.format(new Date());

		// si la date en cours d'utilisation est différente de l'actuelle (toujours en fonction du pattern)
		if ((dateFileInUse == null) || (dateFileInUse != null && !dateFileInUse.equalsIgnoreCase(strDate)) ) {

			if (datePattern!=null && logFileName!=null) {

				dateFileInUse = strDate;

				fileName = logFileName.replaceAll("%date%", strDate);

				super.activateOptions(); // close current file and open new file

			} else {
				System.err.println("Either File or DatePattern options are not set for appender [" + name + "].");
			}
		} else {
			// dans le cas où le fichier aurait été supprimé
			if(!(new File(this.getFile())).exists()) {
				dateFileInUse = null;
				makeNewFileLog();
			}
		}
	}

}

Et maintenant, comment utiliser ce système de log dans une classe :

package fr.waldo.business;

import org.apache.log4j.Logger;

public class UneClasse {

	private final Logger logger = Logger.getLogger("myfunkylog"); //  « myfunkylog » est définie dans le fichier de propriété de Log4j

	public UneClasse() {
		logger.info("Un texte de log utile(ou non)") ;
	}
}

Des questions ?

Tagués avec : ,
Publié dans Java

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

*