How can I disable the default console handler, while using the java logging API?
Asked Answered
A

5

99

Hi I am trying to implement the java logging in my application. I want to use two handlers. A file handler and my own console handler. Both of my handlers work fine. My logging is send to a file and to the console . My logging is also sent to the default console handler, which i do not want. If you run my code you will see extra two line sent to the console. I don't want to use the default console handler. Does anyone know how to disable the default console handler. I only want to use the two handlers I have created.

Handler fh = new FileHandler("test.txt");
fh.setFormatter(formatter);
logger.addHandler(fh);

Handler ch = new ConsoleHandler();
ch.setFormatter(formatter);
logger.addHandler(ch);

import java.util.Date;
import java.util.logging.ConsoleHandler;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

public class LoggingExample {
    private static Logger logger = Logger.getLogger("test");

    static {
        try {
            logger.setLevel(Level.INFO);

            Formatter formatter = new Formatter() {

                @Override
                public String format(LogRecord arg0) {
                    StringBuilder b = new StringBuilder();
                    b.append(new Date());
                    b.append(" ");
                    b.append(arg0.getSourceClassName());
                    b.append(" ");
                    b.append(arg0.getSourceMethodName());
                    b.append(" ");
                    b.append(arg0.getLevel());
                    b.append(" ");
                    b.append(arg0.getMessage());
                    b.append(System.getProperty("line.separator"));
                    return b.toString();
                }

            };

            Handler fh = new FileHandler("test.txt");
            fh.setFormatter(formatter);
            logger.addHandler(fh);

            Handler ch = new ConsoleHandler();
            ch.setFormatter(formatter);
            logger.addHandler(ch);

            LogManager lm = LogManager.getLogManager();
            lm.addLogger(logger);
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        logger.info("why does my test application use the standard console logger ?\n" + " I want only my console handler (Handler ch)\n " + "how can i turn the standard logger to the console off. ??");
    }
}
Apprehensible answered 28/3, 2010 at 14:25 Comment(1)
Can i gently suggest to use b.append(formatMessage(arg0)) instead of b.append(arg0.getMessage()). With the formatMessage method you are making compatible your formatter with the use public void log(Level level, String msg, Object param1) and similar methods.Tamis
F
115

The default console handler is attached to the root logger, which is a parent of all other loggers including yours. So I see two ways to solve your problem:

If this is only affects this particular class of yours, the simplest solution would be to disable passing the logs up to the parent logger:

logger.setUseParentHandlers(false);

If you want to change this behaviour for your whole app, you could remove the default console handler from the root logger altogether before adding your own handlers:

Logger globalLogger = Logger.getLogger("global");
Handler[] handlers = globalLogger.getHandlers();
for(Handler handler : handlers) {
    globalLogger.removeHandler(handler);
}

Note: if you want to use the same log handlers in other classes too, the best way is to move the log configuration into a config file in the long run.

Forelli answered 28/3, 2010 at 14:34 Comment(11)
setUseParentHandlers method works, thanks. how can i remove the default console handler from the root logger ?Apprehensible
@Apprehensible just added the example :-)Strasser
You could also use Logger.getLogger("") - this works for me where "global" does not (may be the result of SLF4J in the mix?)Boru
If you want slf4j I suggest you use this LogManager.getLogManager().reset(); SLF4JBridgeHandler.install();Arianearianie
LogManager.getLogManager().reset() is better than iterating thru and removing handlers.Ghassan
sehugg, I'm also using SLF4J and on Windows "global" works fine. On MacOS "global" returns null but a blank string "" works. Maybe it's the combination of SLF4J and MacOS.Marysa
Using Logger.getLogger("global"); or Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); didn't work for me. I'm using IBM J9 VM (build 2.4, J2RE 1.6.0 IBM J9 2.4). I also think that LogManager.getLogManager().reset() is the best answer to this question. In our situation we don't need a workaround, there is a method in JUL API that does exactly what we need.Equalize
"" is the identifier of the root logger. "global" is a named logger (child of root) which is created by default and shall be used in simple logging scenariosOsgood
since 1.7 Logger.getGlobal()Orbicular
This answer doesn't work for me but the one by Dominique doesWinnie
Even if this is more verbose to clear the handlers by hand, using the LogManager to reset the handlers is risky if we use more than one handler because it will impact every named handlers..Surge
B
118

Just do

LogManager.getLogManager().reset();
Ballottement answered 29/7, 2010 at 14:48 Comment(2)
Thank you, this is the right answer. The answer marked as correct, does not work.Tourist
This should point that this will impact every handler for every named Logger so this could be a problem for a more complex Log system. This should be call once at the beginning of the process to be sure the futur logger won't be impacted. And of course, the one that will need the console will need to receive a ConsoleHandler to by as expected.Surge
F
115

The default console handler is attached to the root logger, which is a parent of all other loggers including yours. So I see two ways to solve your problem:

If this is only affects this particular class of yours, the simplest solution would be to disable passing the logs up to the parent logger:

logger.setUseParentHandlers(false);

If you want to change this behaviour for your whole app, you could remove the default console handler from the root logger altogether before adding your own handlers:

Logger globalLogger = Logger.getLogger("global");
Handler[] handlers = globalLogger.getHandlers();
for(Handler handler : handlers) {
    globalLogger.removeHandler(handler);
}

Note: if you want to use the same log handlers in other classes too, the best way is to move the log configuration into a config file in the long run.

Forelli answered 28/3, 2010 at 14:34 Comment(11)
setUseParentHandlers method works, thanks. how can i remove the default console handler from the root logger ?Apprehensible
@Apprehensible just added the example :-)Strasser
You could also use Logger.getLogger("") - this works for me where "global" does not (may be the result of SLF4J in the mix?)Boru
If you want slf4j I suggest you use this LogManager.getLogManager().reset(); SLF4JBridgeHandler.install();Arianearianie
LogManager.getLogManager().reset() is better than iterating thru and removing handlers.Ghassan
sehugg, I'm also using SLF4J and on Windows "global" works fine. On MacOS "global" returns null but a blank string "" works. Maybe it's the combination of SLF4J and MacOS.Marysa
Using Logger.getLogger("global"); or Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); didn't work for me. I'm using IBM J9 VM (build 2.4, J2RE 1.6.0 IBM J9 2.4). I also think that LogManager.getLogManager().reset() is the best answer to this question. In our situation we don't need a workaround, there is a method in JUL API that does exactly what we need.Equalize
"" is the identifier of the root logger. "global" is a named logger (child of root) which is created by default and shall be used in simple logging scenariosOsgood
since 1.7 Logger.getGlobal()Orbicular
This answer doesn't work for me but the one by Dominique doesWinnie
Even if this is more verbose to clear the handlers by hand, using the LogManager to reset the handlers is risky if we use more than one handler because it will impact every named handlers..Surge
B
22

This is strange but Logger.getLogger("global") does not work in my setup (as well as Logger.getLogger(Logger.GLOBAL_LOGGER_NAME)).

However Logger.getLogger("") does the job well.

Hope this info also helps somebody...

Brack answered 29/6, 2010 at 14:34 Comment(2)
can someone tell us why getLogger(Logger.GLOBAL_LOGGER_NAME) does not work but getLogger("") does?Ommiad
@Ommiad see my comment to this answerOsgood
L
9

Do a reset of the configuration and set the root level to OFF

LogManager.getLogManager().reset();
Logger globalLogger = Logger.getLogger(java.util.logging.Logger.GLOBAL_LOGGER_NAME);
globalLogger.setLevel(java.util.logging.Level.OFF);
Lightfingered answered 15/2, 2011 at 11:48 Comment(0)
T
7

You must instruct your logger not to send its messages on up to its parent logger:

...
import java.util.logging.*;
...
Logger logger = Logger.getLogger(this.getClass().getName());
logger.setUseParentHandlers(false);
...

However, this should be done before adding any more handlers to logger.

Taunyataupe answered 17/3, 2011 at 12:56 Comment(1)
This worked in my case, though I had to add handler manually for this logger.Lebanon

© 2022 - 2024 — McMap. All rights reserved.