Les JavaDocs for Java.util.logging.Level
état:
Les niveaux en ordre décroissant sont:
SEVERE
(valeur la plus élevée)WARNING
INFO
CONFIG
FINE
FINER
FINEST
(valeur la plus basse)import Java.util.logging.*;
class LoggingLevelsBlunder {
public static void main(String[] args) {
Logger logger = Logger.getAnonymousLogger();
logger.setLevel(Level.FINER);
System.out.println("Logging level is: " + logger.getLevel());
for (int ii=0; ii<3; ii++) {
logger.log(Level.FINE, ii + " " + (ii*ii));
logger.log(Level.INFO, ii + " " + (ii*ii));
}
}
}
Logging level is: FINER
Jun 11, 2011 9:39:23 PM LoggingLevelsBlunder main
INFO: 0 0
Jun 11, 2011 9:39:24 PM LoggingLevelsBlunder main
INFO: 1 1
Jun 11, 2011 9:39:24 PM LoggingLevelsBlunder main
INFO: 2 4
Press any key to continue . . .
Mon exemple définit le Level
sur FINER
, donc je m'attendais à voir 2 messages pour chaque boucle. Au lieu de cela, je ne vois qu'un seul message pour chaque boucle (le Level.FINE
_ messages sont manquants).
Que faut-il changer pour voir la sortie FINE
(, FINER
ou FINEST
)?
Grâce à réponse de Vineet Reynolds , cette version fonctionne selon mes attentes. Il affiche 3x INFO
messages et 3x FINE
messages.
import Java.util.logging.*;
class LoggingLevelsBlunder {
public static void main(String[] args) {
Logger logger = Logger.getAnonymousLogger();
// LOG this level to the log
logger.setLevel(Level.FINER);
ConsoleHandler handler = new ConsoleHandler();
// PUBLISH this level
handler.setLevel(Level.FINER);
logger.addHandler(handler);
System.out.println("Logging level is: " + logger.getLevel());
for (int ii=0; ii<3; ii++) {
logger.log(Level.FINE, ii + " " + (ii*ii));
logger.log(Level.INFO, ii + " " + (ii*ii));
}
}
}
Les enregistreurs enregistrent uniquement le message, c’est-à-dire qu’ils créent les enregistrements (ou les demandes d’enregistrement). Ils ne publient pas les messages vers les destinations, qui sont pris en charge par les gestionnaires. Définir le niveau d'un enregistreur ne fait que créer enregistrer les enregistrements correspondant à ce niveau ou à un niveau supérieur.
Vous utilisez peut-être un ConsoleHandler
(je ne peux pas en déduire si votre sortie est System.err ou un fichier, mais je suppose que c'est le premier), qui est par défaut la publication enregistrer les enregistrements du niveau Level.INFO
. Vous devrez configurer ce gestionnaire pour publier les enregistrements de journal de niveau Level.FINER
et plus, pour le résultat souhaité.
Je vous recommande de lire le guide Présentation de Java Logging , afin de comprendre la conception sous-jacente. Le guide couvre la différence entre le concept d'un enregistreur et d'un gestionnaire.
Modification du niveau du gestionnaire
1. Utilisation du fichier de configuration
Le fichier de propriétés Java.util.logging (par défaut, il s’agit du fichier logging.properties
fichier dans JRE_HOME/lib
) peut être modifié pour modifier le niveau par défaut de ConsoleHandler:
Java.util.logging.ConsoleHandler.level = FINER
2. Création de gestionnaires au moment de l'exécution
Ceci n'est pas recommandé car cela entraînerait le remplacement de la configuration globale. Si vous utilisez ceci dans votre base de code, vous obtiendrez une configuration de consignateur impossible à gérer.
Handler consoleHandler = new ConsoleHandler();
consoleHandler.setLevel(Level.FINER);
Logger.getAnonymousLogger().addHandler(consoleHandler);
Le pourquoi
Java.util.logging a un enregistreur racine dont la valeur par défaut est Level.INFO
, Et un ConsoleHandler qui lui est associé qui est également défini par défaut sur Level.INFO
. FINE
est inférieur à INFO
, ainsi les messages fins ne sont pas affichés par défaut.
Solution 1
Créez un enregistreur pour l’ensemble de votre application, par exemple. à partir de votre nom de package ou utilisez Logger.getGlobal()
, et connectez-y votre propre ConsoleLogger. Ensuite, demandez à l'enregistreur racine de se fermer (pour éviter la duplication des messages de niveau supérieur) ou demandez à votre enregistreur de ne transfère pas les journaux à la racine.
public static final Logger applog = Logger.getGlobal();
...
// Create and set handler
Handler systemOut = new ConsoleHandler();
systemOut.setLevel( Level.ALL );
applog.addHandler( systemOut );
applog.setLevel( Level.ALL );
// Prevent logs from processed by default Console handler.
applog.setUseParentHandlers( false ); // Solution 1
Logger.getLogger("").setLevel( Level.OFF ); // Solution 2
Solution 2
Vous pouvez également baisser la barre de l’enregistreur racine.
Vous pouvez les définir par code:
Logger rootLog = Logger.getLogger("");
rootLog.setLevel( Level.FINE );
rootLog.getHandlers()[0].setLevel( Level.FINE ); // Default console handler
Ou avec le fichier de configuration de la journalisation, si vous utilisez l’utilisez :
.level = FINE
Java.util.logging.ConsoleHandler.level = FINE
En abaissant le niveau global, vous pouvez commencer à voir les messages des bibliothèques principales, tels que certains composants Swing ou JavaFX. Dans ce cas, vous pouvez définir un Filtre sur l'enregistreur racine afin de filtrer les messages autres que ceux de votre programme.
pourquoi mon Java la journalisation ne fonctionne pas
fournit un fichier jar qui vous aidera à comprendre pourquoi votre connexion ne fonctionne pas comme prévu. Il vous donne une liste complète de ce que les enregistreurs et les gestionnaires ont été installés et quels niveaux sont définis et à quel niveau de la hiérarchie de journalisation.
[~ # ~] pourquoi [~ # ~]
Comme mentionné par @Sheepy, la raison pour laquelle cela ne fonctionne pas est que Java.util.logging.Logger
A un enregistreur racine dont le nom par défaut est Level.INFO
, Et que ConsoleHandler
est également associé à cet enregistreur racine. La valeur par défaut est Level.INFO
. Par conséquent, pour voir la sortie FINE
(, FINER
ou FINEST
), vous devez définir la valeur par défaut du consignateur racine et de sa valeur ConsoleHandler
. à Level.FINE
comme suit:
Logger.getLogger("").setLevel(Level.FINE);
Logger.getLogger("").getHandlers()[0].setLevel(Level.FINE);
Le problème de votre mise à jour (solution)
Comme mentionné par @mins, les messages seront imprimés deux fois sur la console pour INFO
et au-dessus: tout d'abord par le consignateur anonyme, puis par son parent, le consignateur racine qui possède également un ConsoleHandler
. réglé sur INFO
par défaut. Pour désactiver le consignateur racine, vous devez ajouter cette ligne de code: logger.setUseParentHandlers(false);
Il existe d'autres moyens d'empêcher le traitement des journaux par le gestionnaire de console par défaut du consignateur racine mentionné par @Sheepy, par exemple:
Logger.getLogger("").getHandlers()[0].setLevel( Level.OFF );
Mais Logger.getLogger("").setLevel( Level.OFF );
ne fonctionnera pas car il bloque uniquement le message transmis directement au consignateur racine, et le message ne provient pas d'un consignateur enfant. Pour illustrer le fonctionnement de Logger Hierarchy
, Je dessine le diagramme suivant:
public void setLevel(Level newLevel)
définir le niveau de consignation en spécifiant les niveaux de message qui seront consignés par ce consignateur. Les niveaux de message inférieurs à cette valeur seront supprimés. La valeur de niveau Level.OFF peut être utilisée pour désactiver la journalisation. Si le nouveau niveau est null, cela signifie que ce nœud doit hériter de son niveau de son ancêtre le plus proche avec une valeur de niveau spécifique (non nulle).
Cette solution me semble meilleure en ce qui concerne la maintenabilité et la conception pour le changement:
Créez le fichier de propriété de journalisation en l'incorporant dans le dossier du projet de ressource, à inclure dans le fichier jar:
# Logging
handlers = Java.util.logging.ConsoleHandler
.level = ALL
# Console Logging
Java.util.logging.ConsoleHandler.level = ALL
Chargez le fichier de propriétés à partir du code:
public static Java.net.URL retrieveURLOfJarResource(String resourceName) {
return Thread.currentThread().getContextClassLoader().getResource(resourceName);
}
public synchronized void initializeLogger() {
try (InputStream is = retrieveURLOfJarResource("logging.properties").openStream()) {
LogManager.getLogManager().readConfiguration(is);
} catch (IOException e) {
// ...
}
}
Essayé d'autres variantes, cela peut être approprié
Logger logger = Logger.getLogger(MyClass.class.getName());
Level level = Level.ALL;
for(Handler h : Java.util.logging.Logger.getLogger("").getHandlers())
h.setLevel(level);
logger.setLevel(level);
// this must be shown
logger.fine("fine");
logger.info("info");
J'ai trouvé mon problème réel et cela n'a été mentionné dans aucune réponse: certains de mes tests unitaires ont provoqué l'exécution de code d'initialisation de journalisation à plusieurs reprises dans la même suite de tests, ce qui a gâché la journalisation des derniers tests.