Tout d'abord, l'utilisation de base. Les apparences principales sont les trois suivantes.
Commencez par créer une instance Logger.
Logger logger = Logger.getLogger("nom de l'enregistreur")
Ensuite, créez une instance Handler et enregistrez-la avec le logger. Vous pouvez enregistrer plusieurs gestionnaires.
Cette fois, créez un gestionnaire avec C: \ sample \ sample.log
comme destination de sortie. Si vous voulez sortir dans un fichier, utilisez la classe d'implémentation d'interface Handler`` FileHandler
.
Handler handler = new FileHandler("C:\\sample\\sample.log");
logger.addHandler(handler);
Enfin, créez une instance du formateur et enregistrez-la dans le gestionnaire.
Cette fois, nous utiliserons SimpleFormatter
pour le formater sous une forme facile à lire pour les humains. SimpleFormatter
est une classe d'implémentation de l'interface Formatter
.
Formatter formatter = new SimpleFormatter();
handler.setFormatter(formatter);
Maintenant, vous êtes prêt à partir. Transmettez le message à l'enregistreur et sortez le journal.
logger.log(Level.INFO, "message");
Comme mentionné ci-dessus, lors de la sortie du journal, spécifiez le niveau de journalisation du message. Les 7 types de niveaux de journal suivants sont préparés par java.util.logging. Plus vous descendez, plus le journal devient sérieux.
--FINE ST - Message de trace très détaillé --FINER --Un message de trace assez détaillé --FINE --Message de trace détaillé --CONFIG --Message de configuration statique --INFO --Message d'information --AVERTISSEMENT --Message d'avertissement --SEVERE --Message critique
Vous pouvez configurer l'enregistreur pour qu'il n'émette que les messages au-dessus d'un certain niveau de journal. Par exemple, si vous souhaitez afficher uniquement les messages de niveau INFO ou supérieur, procédez comme suit.
logger.setLevel(Level.INFO);
L'exemple de programme d'utilisation de base est décrit ci-dessous.
BasicLoggingSample
package sample;
import java.io.IOException;
import java.util.function.Supplier;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
public class BasicLoggingSample {
public static void main(String[] arg) throws SecurityException, IOException {
//Obtenez un enregistreur et définissez le niveau de journalisation sur INFO
Logger logger = Logger.getLogger(BasicLoggingSample.class.getName());
logger.setLevel(Level.INFO);
//Créez un gestionnaire et enregistrez-le comme enregistreur
Handler handler = new FileHandler("C:\\sample\\sample.log");
logger.addHandler(handler);
//Créez un formateur et enregistrez-le en tant que gestionnaire
Formatter formatter = new SimpleFormatter();
handler.setFormatter(formatter);
//Message INFO de sortie
logger.log(Level.INFO, "Message INFO");
//Il existe une méthode simple pour afficher chaque message de niveau journal.
logger.finest("MEILLEUR message");
logger.finer("Message FINER");
logger.fine("Message FINE");
logger.config("Message CONFIG");
logger.info("Message INFO");
logger.warning("Message d'alerte");
logger.severe("Message GRAVE");
//En plus de la méthode de transmission du message sous forme de chaîne de caractères, Supplier<String>Il y a aussi un moyen de passer.
Supplier<String> supplier = new Supplier<String>() {
@Override
public String get() {
return "Message d'approvisionnement";
}
};
logger.info(supplier);
//La méthode de sortie du journal lorsqu'une exception se produit est la suivante. La trace de pile Throwable passée en argument est sortie.
logger.log(Level.WARNING, "Une erreur est survenue.", new RuntimeException("Erreur d'exécution"));
}
}
Les enregistreurs ont une structure hiérarchique basée sur les espaces de noms. Par exemple, si vous créez le logger suivant,
Logger logger = Logger.getLogger("com.sample.App");
La structure hiérarchique est la suivante. L'enregistreur parent de «com.sample.App» est «com.sample» et l'enregistreur parent de «com.sample» est «com». De plus, le journal parent de com
sera le journal racine.
Root
└─com
└─sample
└─App
Si l'enregistreur imprime un message, la sortie est également propagée vers l'enregistreur parent. En d'autres termes, dans l'exemple ci-dessus, si vous envoyez un message à l'enregistreur de com.sample.App
, le message sera émis respectivement à partir de com.sample
, com
et de l'enregistreur racine.
Je ne pense pas que ce soit facile à expliquer avec des mots, alors jetons un coup d'œil à l'exemple de programme.
NameSpaceSample
package sample;
import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
public class NameSpaceSample {
public static void main(String[] arg) throws SecurityException, IOException {
//Obtenez chaque enregistreur. Pour obtenir le journal racine, spécifiez un caractère vide dans le nom du journal.
Logger root = Logger.getLogger("");
Logger com = Logger.getLogger("com");
Logger sample = Logger.getLogger("com.sample");
Logger app = Logger.getLogger("com.sample.App");
// com.sample.Les parents d'applications sont com.sample、com.Le parent de sample est com et le parent de com est root logger.
System.out.println(app.getParent() == sample);
System.out.println(app.getParent().getParent() == com);
System.out.println(app.getParent().getParent().getParent() == root);
//L'enregistreur racine a un parent nul.
System.out.println(root.getParent());
//Définissez un gestionnaire pour chaque enregistreur.
Formatter formatter = new SimpleFormatter();
Handler rootHandler = new FileHandler("C:\\sample\\root.log");
root.addHandler(rootHandler);
rootHandler.setFormatter(formatter);
Handler comHandler = new FileHandler("C:\\sample\\com.log");
com.addHandler(comHandler);
comHandler.setFormatter(formatter);
Handler sampleHandler = new FileHandler("C:\\sample\\sample.log");
sample.addHandler(sampleHandler);
sampleHandler.setFormatter(formatter);
Handler appHandler = new FileHandler("C:\\sample\\App.log");
app.addHandler(appHandler);
appHandler.setFormatter(formatter);
//Lorsque vous sortez un message avec l'application, un message est également émis par chaque enregistreur parent.
app.info("Message INFO");
}
}
Lorsque l'exemple de programme est exécuté, les journaux sont envoyés dans root.log
, com.log
, sample.log
et ʻApp.log sous le répertoire
C: \ sample`.
J'ai présenté comment définir le niveau de journalisation dans l'enregistreur et le contrôler afin que seuls les messages au-dessus d'un certain niveau de journal soient sortis, mais si vous voulez un contrôle plus détaillé, utilisez la classe Filter
.
Filter filter = new Filter() {
@Override
public boolean isLoggable(LogRecord record) {
return record.getMessage().contains("Nombre de dossiers traités=");
}
};
logger.setFilter(filter);
Si le filtre est défini comme ci-dessus, seuls les journaux contenant «nombre de processus =» »dans le message seront affichés.
L'explication ci-dessus a montré comment définir un filtre de niveau de journal sur un enregistreur.
En fait, les niveaux de journalisation et les filtres peuvent également être définis dans Handler
.
L'exemple de programme est décrit ci-dessous.
FiltringSample
package sample;
import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Filter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
public class FiltringSample {
public static void main(String[] arg) throws SecurityException, IOException {
//Créer un enregistreur et définir des gestionnaires et des formateurs
Logger logger = Logger.getLogger("sample1");
Handler handler = new FileHandler("C:\\sample\\sample.log");
logger.addHandler(handler);
handler.setFormatter(new SimpleFormatter());
//Réglez le niveau de journal de l'enregistreur sur INFO
logger.setLevel(Level.INFO);
logger.info("Exemple de message"); //Production
//Définir un filtre sur l'enregistreur
Filter filter1 = new Filter() {
@Override
public boolean isLoggable(LogRecord record) {
return record.getMessage().contains("Nombre de dossiers traités=");
}
};
logger.setFilter(filter1);
logger.info("Exemple de message"); //Pas de sortie
logger.info("Exemple de message,Nombre de dossiers traités=1"); //Production
//Définir un filtre sur le gestionnaire
Filter filter2 = (record) -> record.getMessage().contains("Nombre de mises à jour=");
handler.setFilter(filter2);
logger.info("Exemple de message"); //Pas de sortie
logger.info("Exemple de message,Nombre de dossiers traités=1"); //Pas de sortie
logger.info("Exemple de message,Nombre de dossiers traités=1,Nombre de mises à jour=1"); //Production
//Définir le niveau de journalisation dans le gestionnaire
handler.setLevel(Level.WARNING);
logger.info("Exemple de message"); //Pas de sortie
logger.info("Exemple de message,Nombre de dossiers traités=1"); //Pas de sortie
logger.info("Exemple de message,Nombre de dossiers traités=1,Nombre de mises à jour=1"); //Pas de sortie
logger.warning("Message d'alerte,Nombre de dossiers traités=1,Nombre de mises à jour=1"); //Production
}
}
Si vous exécutez ce qui précède, vous pouvez voir que la sortie du journal est limitée par le niveau de journal et le jeu de filtres pour l'enregistreur et le gestionnaire.
Nous avons présenté ci-dessus que les enregistreurs ont une structure hiérarchique et que lorsqu'un message est émis vers l'enregistreur, il se propage vers l'enregistreur parent. En fait, il y a un piège dans ce mécanisme de propagation, et si vous ne comprenez pas correctement le mécanisme, vous risquez de rester coincé dans le pot. (Je m'intègre ...) Cela peut être difficile à comprendre même si vous l'expliquez avec des mots, mais une fois que vous l'expliquez avec des mots, les spécifications pour la propagation à l'enregistreur parent sont les suivantes.
Oui, je pense que c'est difficile à comprendre. Je pense que vous pouvez comprendre cela plus rapidement en regardant directement la logique. En gros, la logique de sortie du journal est celle illustrée dans la figure ci-dessous.
Avez-vous compris? Le filtre de niveau de journal défini sur l'enregistreur est vérifié uniquement sur le premier enregistreur qui reçoit l'appel, alors qu'il est vérifié. Tous les gestionnaires vérifient le filtre de niveau de journal défini dans le gestionnaire.
Deux exemples pour confirmer cela sont décrits ci-dessous.
NameSpaceSample2
package sample;
import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
public class NameSpaceSample2 {
public static void main(String[] arg) throws SecurityException, IOException {
//Obtenez 3 enregistreurs. Définissez le gestionnaire et le formateur.
Logger root = Logger.getLogger("");
Logger sample = Logger.getLogger("sample");
Logger loggerTreeSample = Logger.getLogger("sample.NameSpaceSample2");
Handler rootHandler = new FileHandler("C:\\sample\\root.log");
Handler sampleHandler = new FileHandler("C:\\sample\\sample.log");
Handler NameSpaceSample2Handler = new FileHandler("C:\\sample\\NameSpaceSample2.log");
Formatter formatter = new SimpleFormatter();
rootHandler.setFormatter(formatter);
sampleHandler.setFormatter(formatter);
NameSpaceSample2Handler.setFormatter(formatter);
root.addHandler(rootHandler);
sample.addHandler(sampleHandler);
loggerTreeSample.addHandler(NameSpaceSample2Handler);
//Définissez le niveau de journalisation de l'enregistreur.
root.setLevel(Level.WARNING);
sample.setLevel(Level.INFO);
loggerTreeSample.setLevel(Level.FINE);
//Le gestionnaire est configuré pour autoriser tous les niveaux de journalisation. (Niveau.Le réglage ALL permet la sortie de tous les messages de niveau journal. )
rootHandler.setLevel(Level.ALL);
sampleHandler.setLevel(Level.ALL);
NameSpaceSample2Handler.setLevel(Level.ALL);
//Journal de sortie
root.fine("Sortant de la racine.Message FINE");
root.info("Sortant de la racine.Message INFO");
root.warning("Sortant de la racine.Message d'alerte");
sample.fine("Envoyer à partir de l'échantillon.Message FINE");
sample.info("Envoyer à partir de l'échantillon.Message INFO");
sample.warning("Envoyer à partir de l'échantillon.Message d'alerte");
loggerTreeSample.fine("Appelé depuis NameSpaceSample2Handler.Message FINE");
loggerTreeSample.info("Appelé depuis NameSpaceSample2Handler.Message INFO");
loggerTreeSample.warning("Appelé depuis NameSpaceSample2Handler.Message d'alerte");
}
}
Lorsque ce qui précède est exécuté, le message émis par loggerTreeSample.fine (...)
est C: \\ sample \\ root même s'il est défini comme
root.setLevel (Level.WARNING);. Vous pouvez voir qu'il est sorti vers .log
Voici un autre exemple. La seule différence par rapport à l'exemple ci-dessus est le paramètre de niveau de journal.
NameSpaceSample3
package sample;
import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
public class NameSpaceSample3 {
public static void main(String[] arg) throws SecurityException, IOException {
//Obtenez 3 enregistreurs. Définissez le gestionnaire et le formateur.
Logger root = Logger.getLogger("");
Logger sample = Logger.getLogger("sample");
Logger loggerTreeSample = Logger.getLogger("sample.NameSpaceSample2");
Handler rootHandler = new FileHandler("C:\\sample\\root.log");
Handler sampleHandler = new FileHandler("C:\\sample\\sample.log");
Handler NameSpaceSample3Handler = new FileHandler("C:\\sample\\NameSpaceSample3.log");
Formatter formatter = new SimpleFormatter();
rootHandler.setFormatter(formatter);
sampleHandler.setFormatter(formatter);
NameSpaceSample3Handler.setFormatter(formatter);
root.addHandler(rootHandler);
sample.addHandler(sampleHandler);
loggerTreeSample.addHandler(NameSpaceSample3Handler);
//L'enregistreur est configuré pour autoriser tous les niveaux de journalisation. (Niveau.Le réglage ALL permet la sortie de tous les messages de niveau journal. )
root.setLevel(Level.ALL);
sample.setLevel(Level.ALL);
loggerTreeSample.setLevel(Level.ALL);
//Définissez le niveau de journalisation dans le gestionnaire.
rootHandler.setLevel(Level.WARNING);
sampleHandler.setLevel(Level.INFO);
NameSpaceSample3Handler.setLevel(Level.FINE);
//Journal de sortie
root.fine("Sortant de la racine.Message FINE");
root.info("Sortant de la racine.Message INFO");
root.warning("Sortant de la racine.Message d'alerte");
sample.fine("Envoyer à partir de l'échantillon.Message FINE");
sample.info("Envoyer à partir de l'échantillon.Message INFO");
sample.warning("Envoyer à partir de l'échantillon.Message d'alerte");
loggerTreeSample.fine("Appelé depuis NameSpaceSample3Handler.Message FINE");
loggerTreeSample.info("Appelé depuis NameSpaceSample3Handler.Message INFO");
loggerTreeSample.warning("Appelé depuis NameSpaceSample3Handler.Message d'alerte");
}
}
Si vous exécutez ce qui précède, vous pouvez voir que seuls les journaux de niveau AVERTISSEMENT sont générés dans C: \\ sample \\ root.log
.
Comme vous l'avez peut-être vu dans les exemples de programmes jusqu'à présent, écrire beaucoup de code pour configurer les enregistreurs et les gestionnaires peut être fastidieux. Après tout, je veux pousser la partie de réglage hors du programme et l'écrire dans le fichier de réglage. Par conséquent, la méthode suivante consiste à lire le fichier de paramètres de l'extérieur.
La méthode pour lire le fichier de paramètres à partir du programme est la suivante. Cette fois, j'ai essayé de lire logging.properties
situé dans le même chemin de classe de l'exemple de programme.
Le fichier de configuration doit être lu au format java.util.Properties
.
LogManager.getLogManager().readConfiguration(SettingFileSample.class.getResourceAsStream("logging.properties"));
Le fichier de configuration d'exemple est le suivant. Veuillez vous référer à {java.home} \ lib \ logging.properties
pour une explication détaillée.
logging.properties
#Le paramètre de niveau de journal du gestionnaire de journalisation racine ConsoleHandler a une erreur standard(System.err)Exportez le journal vers.
handlers=java.util.logging.ConsoleHandler
.level=INFO
#Enregistreur utilisé dans l'exemple de programme"sample.SettingFileSample"paramètres de
sample.SettingFileSample.level=FINE
sample.SettingFileSample.handlers=java.util.logging.FileHandler
#Paramètres de ConsoleHandler
java.util.logging.ConsoleHandler.level=INFO
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
#Paramètres FileHandler
java.util.logging.FileHandler.pattern=C:/sample/sample.log
java.util.logging.FileHandler.limit=1000
java.util.logging.FileHandler.count=1
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
L'exemple de programme utilisant le fichier de configuration ci-dessus est décrit ci-dessous.
SettingFileSample
package sample;
import java.io.IOException;
import java.util.logging.LogManager;
import java.util.logging.Logger;
public class SettingFileSample {
public static void main(String[] arg) throws SecurityException, IOException {
LogManager.getLogManager().readConfiguration(SettingFileSample.class.getResourceAsStream("logging.properties"));
Logger logger = Logger.getLogger("sample.SettingFileSample");
logger.finer("Message FINER");
logger.fine("Message FINE");
logger.info("Message INFO");
}
}
C'est bien car il n'y a pas de paramètres de journalisation ou de gestionnaire.
java.util.logging peut également prendre en charge l'internationalisation à l'aide de ResourceBundle. L'exemple de programme est décrit ci-dessous. L'exemple utilise «resource_ja.properties» et «resource_en.properties» dans le même chemin de classe que la classe Java.
ResourceBundleSample
package sample;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.logging.Logger;
public class ResourceBundleSample {
public static void main(String[] arg) {
Logger lggr = Logger.getLogger(ResourceBundleSample.class.getName());
lggr.setResourceBundle(ResourceBundle.getBundle("sample.resource", Locale.JAPANESE));
lggr.info("ID1");
lggr.setResourceBundle(ResourceBundle.getBundle("sample.resource", Locale.ENGLISH));
lggr.info("ID1");
}
}
resource_ja.properties
ID1=Message japonais
resource_en.properties
ID1=english message
Lorsque vous exécutez l'exemple de programme, le premier journal affichera «message japonais» et le second journal affichera «message anglais».
Lorsque Security Manager est activé, les paramètres du journal ne peuvent pas être modifiés par programme. Lorsque l'exemple de programme suivant est exécuté avec Security Manager activé, ʻAccessControlException` est exécuté.
LoggingPermissionSample
package sample;
import java.util.logging.Level;
import java.util.logging.Logger;
public class LoggingPermissionSample {
public static void main(String[] arg) {
Logger lg = Logger.getLogger("");
lg.setLevel(Level.FINE);
lg.fine("fine message");
lg.info("info message");
}
}
Pour autoriser les modifications du journal lorsque Security Manager est activé, écrivez ce qui suit dans votre fichier de stratégie: Pour plus de détails, reportez-vous au Javadoc de LoggerPermission
.
java.policy
grant {
permission java.util.logging.LoggingPermission "control", "";
}
Pour activer le gestionnaire de sécurité, spécifiez java.security.manager
dans l'argument VM comme indiqué ci-dessous.
Pour spécifier explicitement le fichier de stratégie, spécifiez java.security.policy
dans l'argument VM comme indiqué ci-dessous.
java -Djava.security.manager -Djava.security.policy=exemple de chemin de fichier de stratégie.LoggingPermissionSample
Recommended Posts