web-dev-qa-db-fra.com

java.util.logging.Logger ne respecte pas Java.util.logging.Level?

En clair Java SE 6:

Logger l = Logger.getLogger("nameless");
l.setLevel(Level.ALL);
l.fine("somemessage");

Rien n'apparaît dans la console Eclipse. l.info ("") et au-dessus fonctionne très bien, mais tout ce qui est en dessous fine ne semble tout simplement pas fonctionner. Quel est le problème? TIA.

49
yanchenko

Même si le niveau de l'enregistreur est défini sur ALL, le ConsoleHandler (le gestionnaire par défaut de l'enregistreur) a toujours un niveau d'INFO par défaut. Cela vient du fichier logging.properties par défaut dans Java_HOME/jre/lib

55
Kevin

Au lieu de parcourir tous les gestionnaires et de définir le niveau de journalisation, je préfère définir uniquement le niveau du gestionnaire de console:

//get the top Logger
Logger topLogger = Java.util.logging.Logger.getLogger("");

// Handler for console (reuse it if it already exists)
Handler consoleHandler = null;
//see if there is already a console handler
for (Handler handler : topLogger.getHandlers()) {
    if (handler instanceof ConsoleHandler) {
        //found the console handler
        consoleHandler = handler;
        break;
    }
}


if (consoleHandler == null) {
    //there was no console handler found, create a new one
    consoleHandler = new ConsoleHandler();
    topLogger.addHandler(consoleHandler);
}
//set the console handler to fine:
consoleHandler.setLevel(Java.util.logging.Level.FINEST);
35
michel.iamit

Un individu sur mon lieu de travail a constaté que ce qui suit fonctionnait:

public class Foo {
    private final static Logger logger = Logger.getLogger(Foo.class.getName());
    public static final void main(String[] args) {
        ConsoleHandler ch = new ConsoleHandler();
        ch.setLevel(Level.FINEST);
        Foo.logger.addHandler(ch);
        Foo.logger.setLevel(Level.FINEST);
        Foo.logger.finest("test");
    }
}

Si vous venez de définir la racine ou le gestionnaire sur le meilleur (exclusivement), cela ne fonctionne pas. Quand je mets les deux à FINEST alors ça marche. Son explication était:

L'enregistreur et ses gestionnaires ont tous deux des niveaux de journal… L'ordre de filtrage est Enregistreur puis Gestionnaires. Cela signifie qu'il vérifie si le message de journal passe d'abord par le filtre des enregistreurs, puis envoie le message aux gestionnaires individuels pour filtrage.

Il l'a expliqué en utilisant les exemples suivants:

  • Logger myLogger A un niveau de FINEST et un seul ConsoleHandler myHandler Qui a un niveau de INFO

  • myLogger.fine("foo") à message le fait passer devant le filtre de l'enregistreur, mais est stoppé par le filtre du gestionnaire… Rien à sortir.

  • myLogger.info("foo") à passe les deux filtres et foo est sorti.

Maintenant…

  • Logger myLogger A un niveau de INFO et un seul ConsoleHandler myHandler Qui a un niveau de FINEST

  • myLogger.fine("foo") à un message est arrêté par le filtre de l'enregistreur et ne parvient jamais au gestionnaire ... Rien en sortie.

  • myLogger.info("foo") à passe les deux filtres et foo est sorti.

Maintenant…

  • Logger myLogger A un niveau de FINEST et un seul ConsoleHandler myHandler Qui a un niveau de FINEST

  • myLogger.fine("foo") à passe les deux filtres et "foo" est sorti.

  • myLogger.info("foo") à passe les deux filtres et foo est sorti.

17
jwmajors81

D'autres utilisateurs ont déjà donné une bonne réponse pourquoi cela s'est produit (ConsoleHandler a une variable de niveau distincte). Je réutilise le niveau de mon enregistreur d'applications et le copie dans la recherche parent. Fournit également un moyen facile d'actualiser les niveaux à l'exécution à tout moment.

// Set same level all loggers and handlers up to the parent level
// OFF,SEVERE,WARNING,INFO,CONFIG,FINE,FINER,FINEST,ALL
Logger logger = Logger.getLogger(this.getClass().getPackage().getName());
//Level level = Level.parse("FINEST");
Level level = logger.getLevel();
Logger tempLogger = logger;
while(tempLogger != null) {
   tempLogger.setLevel(level);
   for(Handler handler : tempLogger.getHandlers())
      handler.setLevel(level);
   tempLogger = tempLogger.getParent();
}
2
Whome

Vous devez définir le niveau de journalisation sur les gestionnaires de l'enregistreur et l'enregistreur lui-même. L'enregistrement n'est effectué qu'au niveau le plus "grossier" des deux niveaux. Voici une classe de journalisation qui fait le travail.

import Java.io.PrintWriter;
import Java.io.StringWriter;
import Java.time.Instant;
import Java.time.ZoneId;
import Java.time.ZonedDateTime;
import Java.time.format.DateTimeFormatter;
import Java.util.logging.ConsoleHandler;
import Java.util.logging.Formatter;
import Java.util.logging.Handler;
import Java.util.logging.Level;
import Java.util.logging.LogRecord;
import Java.util.logging.Logger;

public class Log {

    private static final Logger logger = Logger.getGlobal();

    private static Level logLevel = Level.INFO;
    static {
        // Remove all the default handlers (usually just one console handler)
        Logger rootLogger = Logger.getLogger("");
        Handler[] rootHandlers = rootLogger.getHandlers();
        for (Handler handler : rootHandlers) {
            rootLogger.removeHandler(handler);
        }

        // Add our own handler
        ConsoleHandler handler = new ConsoleHandler();
        handler.setLevel(logLevel);
        handler.setFormatter(new LogFormatter());
        logger.addHandler(handler);
        logger.setLevel(logLevel);
    }

    public static class LogFormatter extends Formatter {
        @Override
        public String format(LogRecord record) {
            String stackTrace = "";
            Throwable thrown = record.getThrown();
            if (thrown != null) {
                StringWriter stacktraceWriter = new StringWriter();
                try (PrintWriter writer = new PrintWriter(stacktraceWriter)) {
                    thrown.printStackTrace(writer);
                }
                stackTrace = stacktraceWriter.toString();
            }
            return ZonedDateTime.ofInstant(Instant.ofEpochMilli(record.getMillis()), ZoneId.of("UTC")).format(DateTimeFormatter.ISO_ZONED_DATE_TIME) + "\t" + record.getLevel()
                    + "\t" + record.getMessage() + "\n" + stackTrace;
        }
    }

    private static final String classname = Log.class.getName();

    private static String callerRef() {
        StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
        if (stackTraceElements.length < 4) {
            return "";
        } else {
            int i = 1;
            for (; i < stackTraceElements.length; i++) {
                if (stackTraceElements[i].getClassName().equals(classname)) {
                    break;
                }
            }
            for (; i < stackTraceElements.length; i++) {
                if (!stackTraceElements[i].getClassName().equals(classname)) {
                    break;
                }
            }
            if (i < stackTraceElements.length) {
                return stackTraceElements[i].toString();
            } else {
                return "[in unknown method]";
            }
        }
    }

    public static void setLogLevel(Level newLogLevel) {
        logLevel = newLogLevel;
        for (Handler handler : logger.getHandlers()) {
            handler.setLevel(newLogLevel);
        }
        Log.logger.setLevel(newLogLevel);
    }

    public static int getLevelNum() {
        return logLevel.intValue();
    }

    public static int getLevelNum(Level level) {
        return level.intValue();
    }

    public static void fine(String msg) {
        logger.log(Level.FINE, msg);
    }

    public static void info(String msg) {
        logger.log(Level.INFO, msg);
    }

    public static void warning(String msg) {
        logger.log(Level.WARNING, msg + "\t " + callerRef());
    }

    public static void error(String msg) {
        logger.log(Level.SEVERE, msg + "\t " + callerRef());
    }

    public static void exception(String msg, Throwable cause) {
        logger.log(Level.SEVERE, msg + "\t " + callerRef(), cause);
    }

}
2
Luke Hutchison
private final static Logger LOGGER = Logger.getLogger(WoTServer.class.getName());
for(Handler h : LOGGER.getParent().getHandlers()){
    if(h instanceof ConsoleHandler){
        h.setLevel(Level.ALL);
    }
} 
1
d3rbastl3r