web-dev-qa-db-fra.com

Configuration des enregistreurs Log4j par programme

J'essaie d'utiliser SLF4J (avec log4j binding) pour la première fois.

Je voudrais configurer 3 différents enregistreurs nommés qui peuvent être renvoyés par un LoggerFactory qui enregistrera différents niveaux et transmettra les messages à différents appenders:

  • Logger 1 "FileLogger" enregistre DEBUG et ajoute à DailyRollingFileAppender
  • Logger 2 "TracingLogger" enregistre TRACE + et s’ajoute à un JmsAppender
  • Le Logger 3 "ErrorLogger" enregistre ERROR + et est ajouté à un autre JmsAppender

De plus, je veux les configurer par programme (en Java, par opposition à XML ou à un fichier log4j.properties).

J'imagine que, normalement, je définirais ces Loggers quelque part dans un code de démarrage, comme une méthode init(). Cependant, étant donné que je veux utiliser slf4j-log4j, je ne sais pas trop où je pourrais définir des consignateurs et les mettre à la disposition du chemin de classe.

Je ne crois pas qu'il s'agit d'une violation de l'objectif sous-jacent de SLF4J (en tant que façade), car mon code utilisant l'API SLF4J ne saura jamais que ces bûcherons existent. Mon code effectue simplement des appels normaux à l'API SLF4J, qui les transmet ensuite aux enregistreurs log4j qu'il trouve sur le chemin de classe.

Mais comment est-ce que je configure ces log4j sur le classpath ... en Java?!

181
IAmYourFaja

Vous pouvez ajouter/supprimer Appender par programme à Log4j:

  ConsoleAppender console = new ConsoleAppender(); //create appender
  //configure the appender
  String PATTERN = "%d [%p|%c|%C{1}] %m%n";
  console.setLayout(new PatternLayout(PATTERN)); 
  console.setThreshold(Level.FATAL);
  console.activateOptions();
  //add appender to any Logger (here is root)
  Logger.getRootLogger().addAppender(console);

  FileAppender fa = new FileAppender();
  fa.setName("FileLogger");
  fa.setFile("mylog.log");
  fa.setLayout(new PatternLayout("%d %-5p [%c{1}] %m%n"));
  fa.setThreshold(Level.DEBUG);
  fa.setAppend(true);
  fa.activateOptions();

  //add appender to any Logger (here is root)
  Logger.getRootLogger().addAppender(fa);
  //repeat with all other desired appenders

Je suggérerais de le placer dans un init () quelque part, où vous êtes sûr que cela sera exécuté avant toute autre chose. Vous pouvez ensuite supprimer tous les ajouts existants sur le logger racine avec

 Logger.getRootLogger().getLoggerRepository().resetConfiguration();

et commencez par ajouter le vôtre. Vous avez bien besoin de log4j dans le classpath pour que cela fonctionne.

Remarque:
Vous pouvez utiliser n'importe quelle Logger.getLogger(...) pour ajouter des ajouts. Je viens de prendre le consignateur racine, car il se trouve au bas de toutes les choses et gère tout ce qui passe par les autres ajouts dans les autres catégories (sauf configuration contraire en définissant l'indicateur d'additivité).

Si vous avez besoin de savoir comment fonctionne la journalisation et comment on décide où les journaux sont écrits lisez ce manuel pour plus d'informations à ce sujet.
En bref:

  Logger fizz = LoggerFactory.getLogger("com.fizz")

vous donnera un enregistreur pour la catégorie "com.fizz".
Pour l'exemple ci-dessus, cela signifie que tout ce qui est connecté avec celui-ci sera référé à la console et à l'appender de fichier du logger racine.
Si vous ajoutez un appender à Logger.getLogger ("com.fizz"). AddAppender (newAppender), la journalisation à partir de fizz sera gérée par tous les appendeurs du logger racine et le newAppender.
Vous ne créez pas de consignateurs avec la configuration, vous fournissez simplement des gestionnaires pour toutes les catégories possibles de votre système.

270
oers

On dirait que vous essayez d’utiliser log4j à partir des "deux extrémités" (les utilisateurs et les utilisateurs de la configuration).

Si vous souhaitez utiliser l'API slf4j avec un code mais que vous déterminez à l'avance (et par programme) la configuration des enregistreurs log4j que le chemin d'accès aux classes renverra, vous devez absolument avoir une sorte d'adaptation de journalisation qui utilise de construction paresseuse.

public class YourLoggingWrapper {
    private static boolean loggingIsInitialized = false;

    public YourLoggingWrapper() {
        // ...blah
    }

    public static void debug(String debugMsg) {
        log(LogLevel.Debug, debugMsg);
    }

    // Same for all other log levels your want to handle.
    // You mentioned TRACE and ERROR.

    private static void log(LogLevel level, String logMsg) {
        if(!loggingIsInitialized)
            initLogging();

        org.slf4j.Logger slf4jLogger = org.slf4j.LoggerFactory.getLogger("DebugLogger");

        switch(level) {
        case: Debug:
            logger.debug(logMsg);
            break;
        default:
            // whatever
        }
    }

    // log4j logging is lazily constructed; it gets initialized
    // the first time the invoking app calls a log method
    private static void initLogging() {
        loggingIsInitialized = true;

        org.Apache.log4j.Logger debugLogger = org.Apache.log4j.LoggerFactory.getLogger("DebugLogger");

        // Now all the same configuration code that @oers suggested applies...
        // configure the logger, configure and add its appenders, etc.
        debugLogger.addAppender(someConfiguredFileAppender);
    }

Avec cette approche, vous n'avez pas à vous demander où et quand vos enregistreurs log4j seront configurés. La première fois que le classpath les demande, ils sont construits paresseusement, renvoyés et rendus disponibles via slf4j. J'espère que cela a aidé!

45
IAmYourFaja

Si vous avez défini un générateur d'appels dans les propriétés log4j et souhaitez le mettre à jour par programme, définissez le nom dans les propriétés log4j et récupérez-le par son nom.

Voici un exemple d'entrée log4j.properties:

log4j.appender.stdout.Name=console
log4j.appender.stdout=org.Apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.Threshold=INFO

Pour le mettre à jour, procédez comme suit:

((ConsoleAppender) Logger.getRootLogger().getAppender("console")).setThreshold(Level.DEBUG);
3
Kyle Shrader