199 votes

Configuration programmée des enregistreurs Log4j

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

J'aimerais configurer trois enregistreurs nommés différents qui peuvent être renvoyés par un LoggerFactory, qui enregistrent différents niveaux et envoient les messages à différents appenders :

  • Logger 1 "FileLogger" enregistre DEBUG et s'ajoute à DailyRollingFileAppender
  • Le logger 2 "TracingLogger" enregistre TRACE+ et l'ajoute à un fichier de type JmsAppender
  • Le logger 3 "ErrorLogger" enregistre ERROR+ et l'ajoute à un autre logger. JmsAppender

En outre, je souhaite qu'ils soient configurés de manière programmatique (en Java, par opposition à XML ou à un fichier de type log4j.properties ).

J'imagine qu'en temps normal, je définirais ceux-ci Logger s quelque part dans un code d'amorçage, comme une init() méthode. Cependant, comme je veux utiliser slf4j-log4j Je ne sais pas où je pourrais définir les enregistreurs et les rendre disponibles dans le classpath.

Je ne sais pas. croire 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 loggers existent. Mon code fait simplement des appels normaux à l'API SLF4J, qui les transmet ensuite aux loggers log4j qu'il trouve dans le classpath.

Mais comment configurer ces loggers log4j sur le classpath...en Java !

0 votes

4 votes

Pour log4j 1.x utilisez la réponse acceptée ci-dessous pour 2.x voir logging.apache.org/log4j/2.x/manual/customconfig.html

292voto

oers Points 9920

Vous pouvez ajouter/supprimer Appender de manière programmatique à 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 vous suggère de le mettre 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 appenders existants sur le logger Root avec

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

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

Remarques :
Vous pouvez prendre n'importe quel Logger.getLogger(...) vous aimez ajouter des appendices. J'ai simplement pris le logger Root parce qu'il est à la base de tout et qu'il traitera tout ce qui est passé par d'autres appenders dans d'autres catégories (sauf si configuré autrement en mettant le drapeau d'additivité).

Si vous avez besoin de savoir comment fonctionne la journalisation et comment est décidé l'endroit où les journaux sont écrits lire ce manuel pour plus d'informations à ce sujet.
En bref :

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

vous donnera un logger pour la catégorie "com.fizz".
Pour l'exemple ci-dessus, cela signifie que tout ce qui est consigné avec elle sera renvoyé à la console et à l'expéditeur de fichiers sur le logger Root.
Si vous ajoutez un appender à Logger.getLogger("com.fizz").addAppender(newAppender) alors la journalisation de fizz seront gérés par tous les appenders du logger Root et du logger newAppender .
Vous ne créez pas de Loggers avec la configuration, vous fournissez simplement des handlers pour toutes les catégories possibles dans votre système.

2 votes

Merci oers ! Petite question - J'ai remarqué que vous ajoutez les appenders au Root Logger. Y a-t-il une raison à cela ?

0 votes

Et, plus important encore, je devrai spécifier quel enregistreur récupérer à partir de la LoggerFactory de SLF4J. Est-il possible de demander à SLF4J le logger Root de log4j ?

3 votes

@AdamTannon Vous pouvez prendre n'importe quel Logger.getLogger(...) que vous voulez. J'ai juste pris le logger Root parce qu'il est à la base de tout et qu'il gérera tout ce qui est passé par d'autres appenders dans d'autres catégories (sauf configuration contraire). Voir la hiérarchie des enregistreurs

48voto

IAmYourFaja Points 1122

Il semble que vous essayez d'utiliser log4j des "deux côtés" (du côté du consommateur et du côté de la configuration).

Si vous voulez coder contre l'api slf4j mais déterminer à l'avance (et de manière programmatique) la configuration des loggers log4j que le classpath retournera, vous devez ont absolument pour avoir une sorte d'adaptation de la journalisation qui utilise la 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 besoin de vous soucier de l'endroit et du moment où vos loggers log4j sont configurés. La première fois que le classpath les demande, ils sont construits paresseusement, renvoyés et mis à disposition via slf4j. J'espère que cela vous a aidé !

2 votes

C'est réussi ! Merci beaucoup pour cet exemple utile ! @Oers - merci d'avoir essayé de me guider dans la bonne direction - je vais te donner le chèque vert pour ton dévouement mais je dois donner la prime à zharvey parce que c'était exactement ce que je cherchais. Merci encore à tous !

6voto

iamabhishek Points 157

Si quelqu'un cherche à configurer log4j2 de manière programmatique en Java, ce lien pourrait l'aider : ( https://www.studytonight.com/post/log4j2-programmatic-configuration-in-java-class )

Voici le code de base pour configurer un Appender de console :

ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();

builder.setStatusLevel(Level.DEBUG);
// naming the logger configuration
builder.setConfigurationName("DefaultLogger");

// create a console appender
AppenderComponentBuilder appenderBuilder = builder.newAppender("Console", "CONSOLE")
                .addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
// add a layout like pattern, json etc
appenderBuilder.add(builder.newLayout("PatternLayout")
                .addAttribute("pattern", "%d %p %c [%t] %m%n"));
RootLoggerComponentBuilder rootLogger = builder.newRootLogger(Level.DEBUG);
rootLogger.add(builder.newAppenderRef("Console"));

builder.add(appenderBuilder);
builder.add(rootLogger);
Configurator.reconfigure(builder.build());

Ceci reconfigurera la configuration par défaut rootLogger et sera également créer un nouvel appender .

4voto

Kyle Shrader Points 524

Dans le cas où vous avez défini un appender dans les propriétés de log4j et que vous souhaitez le mettre à jour de manière programmatique, définissez le nom dans les propriétés de log4j et obtenez-le par son nom.

Voici un exemple d'entrée dans 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);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X