bw_dev
bw_dev

Reputation: 795

java.util.logging. console handler doesn't logs messages below the INFO level

The following is the code of my logger. Logging to file works perfect, but console handler doesn't print any message bellow the Level.INFO.

public class ServerLogger {

    /*
     * Log file size 
     */
    final private static int FILE_SIZE = 1024 * 100;

    /**
     * Creates and return server logger
     * 
     * @param dir log files directory
     * @param consoleEnabled if set to true then logging to console is enabled 
     * @param debugEnabled if set to true then debug level of logging is enabled
     * 
     * @return sever logger
     * 
     * @throws SecurityException
     * @throws IOException
     */
    public static Logger getLogger(final String dir, final boolean consoleEnabled, final boolean debugEnabled) 
    throws SecurityException, IOException {

        Logger logger = Logger.getLogger(Server.class.getName());
        logger.setUseParentHandlers(false);
    
        /* 
         * remove all handlers if any
         */
        Handler[] handlers = logger.getHandlers();
        
        if (handlers.length > 0) {
            for (Handler handler : handlers)
                logger.removeHandler(handler);
        }
                
        /*
         * create formatter 
         */
        Formatter formatter = new LineFormatter();
        
        /*
         * if console logging is enabled then add console handler
         */
        if (consoleEnabled) {
            ConsoleHandler consoleHandler =  new ConsoleHandler();
            consoleHandler.setFormatter(formatter);
            logger.addHandler(consoleHandler);
        }
    
        
        /*
         * add file handler
         */
        String nameTemplate = dir + "\\" + "server-log%g.txt";

        FileHandler fileHandler = new FileHandler(nameTemplate, FILE_SIZE, 10);
        fileHandler.setFormatter(formatter);
        logger.addHandler(fileHandler);
        
            
        Level level = debugEnabled ? Level.FINE : Level.INFO;
        logger.setLevel(level);
        
        return logger;
    }

    
    static private class LineFormatter extends Formatter {

        @Override
        public String format(LogRecord record) {
            return String.format("[%1$tF %1$tT] [%4$-7s] %5$s %n", record.getMillis(), record.getSourceMethodName(),
                   record.getLoggerName(), record.getLevel(), record.getMessage(), record.getThrown());
        }
    };
    
    
    
    public static void main(String[] args) throws SecurityException, IOException {
        
        //test
        Logger logger = ServerLogger.getLogger("C:\\logs", true, true);
        
        logger.severe("severe");
        logger.warning("warning");
        logger.info("info");
        logger.config("config");
        logger.fine("fine");
        logger.finer("finer");
        logger.finest("finest");
            
    } 

I replaced ConsoleHandler with StreamHandler but this doesn't help. The replacement of logger.setLevel(level) with logger.setLevel(Level.ALL) doesn't help too. Set level of handlers using handler.set(Level level) doesn't change something. The messages on console are:

[2020-12-30 22:09:59] [SEVERE ] severe 
[2020-12-30 22:10:00] [WARNING] warning 
[2020-12-30 22:10:00] [INFO   ] info 

Could you please help.

Upvotes: 0

Views: 1005

Answers (1)

jmehrens
jmehrens

Reputation: 11045

Always pin your logger so it can't be garbage collected. This is done like:

private static final Logger logger = Logger.getLogger(Server.class.getName());

If the logger is garbage collected all of your changes are lost and fallback to the logging.properties.

Next issue is that if you are programmatically removing handlers you have to close them too.

 if (handlers.length > 0) { //The if is not needed, just the for loop.
        for (Handler handler : handlers) {
            logger.removeHandler(handler);
            handler.close(); //Don't leak resources.
        }
 }

Next issue is that you have to set your Console handler level to all:

ConsoleHandler consoleHandler =  new ConsoleHandler();
consoleHandler.setFormatter(formatter);
consoleHandler.setLevel(Level.ALL);
//consoleHandler.setLevel(debugEnabled ? Level.FINE : Level.INFO); //This would work too.

This allows your handler to accept log records lower than INFO.

While it 'works' to have a static method to setup the log configuration you really only want to set the configuration once. Changing the logger tree at runtime is racy and can cause you to lose messages. You should either use a logger configuration file, a logger class, or a static initializer block so the configuration loads once and only once.

Careful with using the StreamHandler + System.err or System.out. The closing on the StreamHandler implicit or explicitly will close the system stream it is wrapping which will stop all output to console. The ConsoleHandler will not do this.

Upvotes: 1

Related Questions