Wie kann ich den Standard-Konsolenhandler deaktivieren, während ich die Java-Protokollierungs-API verwende?

91

Hallo, ich versuche, die Java-Protokollierung in meiner Anwendung zu implementieren. Ich möchte zwei Handler verwenden. Ein Dateihandler und mein eigener Konsolenhandler. Meine beiden Handler funktionieren gut. Meine Protokollierung wird an eine Datei und an die Konsole gesendet. Meine Protokollierung wird auch an den Standard-Konsolenhandler gesendet, den ich nicht möchte. Wenn Sie meinen Code ausführen, werden zusätzliche zwei Zeilen an die Konsole gesendet. Ich möchte den Standard-Konsolenhandler nicht verwenden. Weiß jemand, wie man den Standard-Konsolenhandler deaktiviert? Ich möchte nur die beiden von mir erstellten Handler verwenden.

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. ??");
    }
}
Loudiyimo
quelle
1
Kann ich sanft vorschlagen, b.append(formatMessage(arg0))anstelle von zu verwenden b.append(arg0.getMessage()). Mit der formatMessageMethode machen Sie Ihren Formatierer mit der Verwendung public void log(Level level, String msg, Object param1)und ähnlichen Methoden kompatibel .
Victor

Antworten:

102

Der Standard-Konsolenhandler ist an den Root-Logger angehängt, der allen anderen Loggern, einschließlich Ihrem, übergeordnet ist. Ich sehe also zwei Möglichkeiten, um Ihr Problem zu lösen:

Wenn dies nur Ihre bestimmte Klasse betrifft, besteht die einfachste Lösung darin, die Übergabe der Protokolle an den übergeordneten Protokollierer zu deaktivieren:

logger.setUseParentHandlers(false);

Wenn Sie dieses Verhalten für Ihre gesamte App ändern möchten, können Sie den Standard-Konsolenhandler vollständig aus dem Root-Logger entfernen, bevor Sie Ihre eigenen Handler hinzufügen:

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

Hinweis: Wenn Sie dieselben Protokollhandler auch in anderen Klassen verwenden möchten, ist es am besten, die Protokollkonfiguration langfristig in eine Konfigurationsdatei zu verschieben.

Péter Török
quelle
2
Die Methode setUseParentHandlers funktioniert, danke. Wie kann ich den Standard-Konsolenhandler aus dem Root-Logger entfernen?
Loudiyimo
10
Sie können auch Logger.getLogger ("") verwenden - dies funktioniert bei mir, wo "global" nicht funktioniert (möglicherweise das Ergebnis von SLF4J in der Mischung?)
sehugg
2
Wenn Sie slf4j wollen, schlage ich vor, dass Sie dies verwenden LogManager.getLogManager().reset(); SLF4JBridgeHandler.install();
Somatik
8
"" ist die Kennung des Root-Loggers. "global" ist ein benannter Logger (Kind von root), der standardmäßig erstellt wird und in einfachen Protokollierungsszenarien verwendet werden soll
Paolo Fulgoni
1
Diese Antwort funktioniert nicht für mich, aber die von Dominique
BullyWiiPlaza
107

Mach einfach

LogManager.getLogManager().reset();
Dominique
quelle
1
Danke, das ist die richtige Antwort. Die als richtig gekennzeichnete Antwort funktioniert nicht.
Andreas L.
1
Dies sollte darauf hinweisen, dass dies Auswirkungen auf jeden Handler für jeden Namen hat, Loggersodass dies ein Problem für ein komplexeres Protokollsystem sein kann. Dies sollte zu Beginn des Prozesses einmal aufgerufen werden, um sicherzustellen, dass der Futur-Logger nicht betroffen ist. Und natürlich muss derjenige, der die Konsole benötigt, ConsoleHandlerwie erwartet eine Antwort erhalten.
AxelH
20

Dies ist seltsam, Logger.getLogger("global") funktioniert aber nicht in meinem Setup (sowie Logger.getLogger(Logger.GLOBAL_LOGGER_NAME)).

Allerdings Logger.getLogger("")macht den Job gut.

Hoffe diese Info hilft auch jemandem ...

Dime
quelle
3
Kann uns jemand sagen, warum getLogger (Logger.GLOBAL_LOGGER_NAME) nicht funktioniert, getLogger ("") jedoch?
Deinocheirus
2
@deinocheirus siehe meinen Kommentar zu dieser Antwort
Paolo Fulgoni
9

Führen Sie einen Reset der Konfiguration durch und setzen Sie den Root-Level auf OFF

LogManager.getLogManager().reset();
Logger globalLogger = Logger.getLogger(java.util.logging.Logger.GLOBAL_LOGGER_NAME);
globalLogger.setLevel(java.util.logging.Level.OFF);
Manuel
quelle
5

Sie müssen Ihren Logger anweisen, seine Nachrichten nicht an den übergeordneten Logger weiterzuleiten:

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

Dies sollte jedoch erfolgen, bevor dem Logger weitere Handler hinzugefügt werden.

Ich sag bloß
quelle
Dies funktionierte in meinem Fall, obwohl ich den Handler für diesen Logger manuell hinzufügen musste.
Sachin Gorade