Susie
Susie

Reputation: 5138

Close log files

This project has been handed down to me, so I do not know much about it. There is a method where log (java.util.logging.Logger) is used and it creates two log files:

First file: fileName.log

Second file: fileName.log.lck

In Linux when I do lsof, I see these two files as open. How do I close these two files?

The reason why I want to close these files is this method is run multiple times a day and after couple of weeks the number of open files reaches a limit (around 1000), at which point our system stops working. When we restart our process ("Job Controller" which does the logging) the number of log files open goes to 0 and it works again.

This is what's been done to do logging

private static Logger log = Logger.getLogger(MyClass.class.getPackage().getName());
try{
    log.logp(Level.SEVERE, "com.MyClass", "run", "It failed");
}

This is what I tried to do to close the files in the finally block but it didn't work

finally{
    Handler[] handler =   log.getHandlers();
    for(Handler h: handler){
        h.close();
    }
}

Upvotes: 8

Views: 12159

Answers (3)

KUL
KUL

Reputation: 491

I'll leave it here for myself:

public class JQLogger {

    public static Logger getLogger(String logName) {
        if (LogManager.getLogManager().getLogger(logName) != null
                && LogManager.getLogManager().getLogger(logName).getHandlers().length > 0)
            return LogManager.getLogManager().getLogger(logName);

        String logPath = "log/";
        if (Files.notExists(Paths.get(logPath)))
            try {
                Files.createDirectories(Paths.get(logPath));
            } catch (IOException e) {
                e.printStackTrace();
            }
        Logger logger = Logger.getLogger(logName);
        logger.setLevel(Level.INFO);
        logger.setUseParentHandlers(false);

        ConsoleHandler consoleHandler = new ConsoleHandler();
        FileHandler fileHandler;
        try {
            fileHandler = new FileHandler(logPath + logger.getName() + ".%g.log", 52428800, 3, true);
            fileHandler.setFormatter(JQLogger.getFormatter());
            logger.addHandler(fileHandler);
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        consoleHandler.setFormatter(JQLogger.getFormatter());
        logger.addHandler(consoleHandler);

        return logger;
    }

    private static Formatter getFormatter() {
        return new SimpleFormatter() {
            private String format = "[%1$tF %1$tT.%1$tL] [%2$-7s] %3$s %n";

            @Override
            public synchronized String format(LogRecord lr) {
                return String.format(format, new Date(lr.getMillis()), lr.getLevel().getLocalizedName(),
                        lr.getMessage());
            }
        };
    }

    public static void closeLogger(Logger logger) {
        for (Handler h : logger.getHandlers()) {
            h.close();
            logger.removeHandler(h);
        }
    }

}

Upvotes: 0

Shaybc
Shaybc

Reputation: 3147

I simply use:

LogManager.getLogManager().reset();

this will cancel all your log settings (log file path, file name pattern, formatter...) but it will stop using the logger close the lock file and release logger to

Upvotes: 9

Andrzej Jozwik
Andrzej Jozwik

Reputation: 14649

First solution

If you do not want to modify your code use: How to send java.util.logging to log4j? java.util.logging.Logger to Logback using SLF4J?

I use log4j or logback. Both have Rolling File Appender (old files are removed) or Date/Time File appender.

Second solution

For logging the best usage is rolling file.

String filePattern = " fileName%.log";
int limit = 1000 * 1000; // 1 Mb
int numLogFiles = 3;
FileHandler fh = new FileHandler(filePattern, limit, numLogFiles);

// Add to logger
Logger logger = Logger.getLogger(MyClass.class.getPackage().getName());
logger.addHandler(fh);

I do not know if you can add globally file handler.

Upvotes: 2

Related Questions