Reputation: 932
I am using java.util.logging framework to implement logging in my JSF application. I have successfully done implementing this, but however I have a new requirement to rotate the logs and create a new log file for each day.
I am not able to figure out how this can be implemented. Any hints on implementation would be highly appreciated. Thanks.
This is how I have configured my logger:
myLogger = Logger.getLogger("info.aio");
fileHandler = new FileHandler("aioinfo.log", 1048576, 100, true);
fileHandler.setFormatter(new SimpleFormatter());
myLogger.addHandler(fileHandler);
Upvotes: 9
Views: 13465
Reputation: 409
Create a task that executes every day at midnight using ScheduledThreadPoolExecutor and in the task dispose and close the current FileHandler and then create a new one with the updated file name.
Something like this should work:
public class DailyLogger {
private static Logger logger;
private static FileHandler fh;
public static Logger getLogger() {
if(logger == null){
initLogger();
ScheduledThreadPoolExecutor sch = (ScheduledThreadPoolExecutor)Executors.newScheduledThreadPool(1);
// Create a task for one-shot execution using schedule()
Runnable renameLoggerFile = new Runnable(){
// int countRuns = 0; // For testing only
@Override
public void run() {
fh.flush();
fh.close();
try {
fh = createFilehandler(new java.sql.Date(System.currentTimeMillis()).toString());
// fh = createFilehandler(new java.sql.Date(System.currentTimeMillis()).toString()+"_"+countRuns++); // for testing
SimpleFormatter formatter = new SimpleFormatter();
fh.setFormatter(formatter);
logger.addHandler(fh);
logger.warning("Runnable executed, new FileHandler is in use!");
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
Calendar c = Calendar.getInstance();
long now = c.getTimeInMillis();
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
long passed = now - c.getTimeInMillis();
long secondsPassedToday = passed / 1000;
long secondsInDay = 86400;
TimeUnit timeUnit = TimeUnit.SECONDS;
// sch.scheduleAtFixedRate(renameLoggerFile, 5, 10, timeUnit); // for testing
long initialDelay = secondsInDay - secondsPassedToday;
long relaunchPeriod = secondsInDay;
sch.scheduleAtFixedRate(renameLoggerFile, initialDelay, relaunchPeriod, timeUnit);
}
return logger;
}
private static FileHandler createFilehandler(String dateForName) throws SecurityException, IOException{
String folder = "log";
File fileFolder = new File(folder);
// Create folder log if it doesn't exist
if(!fileFolder.exists()){
fileFolder.mkdirs();
}
dateForName = folder + File.separator + dateForName + ".log";
boolean appendToFile = true;
return new FileHandler(dateForName, appendToFile);
}
private static void initLogger(){
String folder = "log";
File fileFolder = new File(folder);
// Create folder "log" if it doesn't exist
if(!fileFolder.exists()){
fileFolder.mkdirs();
}
logger = Logger.getLogger("DailyLogger");
try {
// This block configure the logger with handler and formatter
boolean appendToFile = true;
fh = new FileHandler(folder + File.separator + new java.sql.Date(System.currentTimeMillis()) + ".log", appendToFile);
logger.addHandler(fh);
SimpleFormatter formatter = new SimpleFormatter();
fh.setFormatter(formatter);
// the following statement is used to log any messages
logger.info("DailyLogger initialized...");
} catch (SecurityException e) {
logger.warning("Problem at initializing logger... " + e.getMessage());
} catch (IOException e) {
logger.warning("Problem at initializing logger... " + e.getMessage());
}
}
}
Upvotes: 1
Reputation: 11045
Since you are using code to setup your FileHandler then you can add code to close and recreate the FileHandler using the '%g'.
public static void main(String[] args) throws Exception {
//create aioinfo0.log.
install();
//rename aioinfo0.log to aioinfo1.log and create aioinfo0.log.
install();
}
private static final Logger myLogger = Logger.getLogger("info.aio");
private static volatile FileHandler fileHandler;
private static void install() throws IOException {
FileHandler fh = fileHandler;
if (fh != null) {
myLogger.removeHandler(fh);
fh.close(); //Release any file lock.
}
fileHandler = rotate("aioinfo%g.log", 1048576, 100, true);
fileHandler.setFormatter(new SimpleFormatter());
myLogger.addHandler(fileHandler);
}
private static FileHandler rotate(String pattern, int limit, int count, boolean append) throws IOException {
if (pattern == null) {
LogManager m = LogManager.getLogManager();
String p = FileHandler.class.getName();
pattern = m.getProperty(p + ".pattern");
if (pattern == null) {
pattern = "%h/java%u.log";
}
}
new FileHandler(pattern, 0, count, false).close(); //Trigger rotate.
return new FileHandler(pattern, limit, count, append);
}
If you want it to work automatically you can simply create a proxy handler for the FileHandler to handle closing and recreating files each day.
Upvotes: 5
Reputation: 18119
Java.util.logging does not support rotating on a daily basis, see this bug report: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6350749
Alternatively, you could use logback, log4j or log4j2 and slf4j to tunnel JUL (see http://www.slf4j.org/legacy.html#jul-to-slf4j). All of the mentioned frameworks support date-based file rotation.
HTH, Mark
Upvotes: 1