J’ai eu quelques problèmes avec la libraire de Logging standard à Java (java.util.logging).
- Aucun support pour les fichiers de configuration
- Fin du logging lors de la supression ou de la modification du fichier de log
J’ai donc codé un wrapper pour me faciliter la vie et réduire le code dans chaque classes qui veut logger quelque chose. Ce wrapper résout les problèmes ennoncés plus haut et supporte le reload à chaud. Lorsqu’on change un paramètre dans le fichier de configuration, celui-ci est automatiquement chargé lors du prochain log. Il détecte la modfication à l’aide de la classe ConfigFile.
Il est maintenant super simple de l’appeller. Dans n’importe quelle classe du projet:
LogFactory.log("org.limoilux.demo", Level.WARNING, "Need a coffee");
Voici la source de LogFactory, ConfigFile et le fichier de configurations.
LogFactory.java
package org.limoilux.demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;
public class LogFactory {
private static final String LOG_CONF_FILE_PATH = "conf/log.properties";
private static final ConfigFile confFile = new ConfigFile();
private static String logFileName = "log/demo.log";
private static long logFileLength = 0;
public static void log(String logger_name, Level l, String msg)
{
try
{
if (!LogFactory.isInitialized())
{
LogFactory.initialize();
}
}
catch (Exception e)
{
Logger.getLogger(logger_name).log(Level.SEVERE, e.toString());
}
Logger.getLogger(logger_name).log(l, msg);
try
{
LogFactory.logFileLength =
new File(LogFactory.logFileName).length();
}
catch (Exception e)
{
Logger.getLogger(logger_name).log(Level.SEVERE, e.toString() +
" cannot get logger file length");
}
}
private static boolean isInitialized() throws Exception
{
if (!LogFactory.confFile.isInitialized(LogFactory.LOG_CONF_FILE_PATH))
{
return false;
}
try
{
if (!LogFactory.logFileExists())
{
return false;
}
if (LogFactory.logFileChanged())
{
return false;
}
}
catch (Exception ex)
{
throw ex;
}
return true;
}
private static boolean logFileExists() throws Exception
{
try
{
LogFactory.refreshLogFileName();
}
catch (IOException ex)
{
throw ex;
}
catch (Exception e)
{
throw e;
}
if (!new File(LogFactory.logFileName).exists())
{
return false;
}
return true;
}
private static void refreshLogFileName() throws IOException, Exception
{
Properties properties = new Properties();
try
{
properties.load(new FileInputStream(LogFactory.LOG_CONF_FILE_PATH));
String filename = properties.
getProperty("java.util.logging.FileHandler.pattern");
if (filename == null)
{
throw new Exception(
"No filename found in log configuration file");
}
LogFactory.logFileName = filename;
LogFactory.logFileLength = new File(filename).length();
}
catch (IOException e)
{
throw e;
}
}
public static void initialize() throws Exception
{
Properties prop = System.getProperties();
prop.setProperty("java.util.logging.config.file",
LogFactory.LOG_CONF_FILE_PATH);
try
{
LogManager.getLogManager().readConfiguration();
}
catch (Exception e)
{
throw e;
}
}
public static boolean logFileChanged() throws Exception
{
boolean has_changed = true;
long new_file_length = 0;
if (LogFactory.logFileLength == 0)
{
return true;
}
try
{
LogFactory.refreshLogFileName();
new_file_length =
new File(LogFactory.logFileName).length();
if (new_file_length == LogFactory.logFileLength)
{
has_changed = false;
}
}
catch (IOException ex)
{
throw ex;
}
catch (Exception e)
{
throw e;
}
return has_changed;
}
}
ConfigFile.java
package org.limoilux.demo;
import java.io.File;
/**
*
* @author avezina
*/
public class ConfigFile {
private File configFile;
public ConfigFile()
{
this.configFile = null;
}
/**
* This will initialize the ConfigFile if it was not
* @param filename
* @return
*/
public boolean isInitialized(String filename)
{
File f = new File(filename);
if(this.configFile == null)
{
this.configFile = f;
return false;
}
if (this.configFile.compareTo(f) != 0)
{
return false;
}
this.configFile = f;
return true;
}
public void initialize(String filename)
{
this.configFile = new File(filename);
}
}
Pour configurer le logger, il suffit de créer le fichier log.properties dans le répertoire conf. LogFactory s’occupera de détecter les changements et de charger les paramètres.
conf/log.properties
handlers = java.util.logging.FileHandler .level = WARNING java.util.logging.FileHandler.pattern = log/demo.log java.util.logging.FileHandler.limit = 50000 java.util.logging.FileHandler.append = true org.vencomm.demo.level = INFO