web-dev-qa-db-fra.com

Log4J2 - attribution du nom du fichier appender au moment de l'exécution

J'ai un fichier de configuration log4j2.xml dans le chemin de classe. L'un des appender est un appender File, et je voudrais définir le nom du fichier cible au moment de l'exécution dans l'application Java.

Selon le docs je devrais pouvoir utiliser un double "$" et un préfixe de contexte dans le fichier log4j2.xml:

<appenders>
    <File name="MyFile" fileName="$${sys:logFilename}">
        <PatternLayout pattern="%-4r %d{${datestamp}} [%t] %-5level %logger{36} - %msg%n"/>
    </File>
</appenders>

où le préfixe "sys" indique que le configurateur recherchera la propriété "logFilename" dans les propriétés du système. Donc dans l'application, j'appelle (assez tôt):

System.setProperty("logFilename", filename);

J'ai également activé la reconfiguration automatique pour log4j2 dans le fichier xml:

<configuration status="debug" monitorInterval="5">>

Malheureusement, cela n'a aucun effet et le fichier journal n'est jamais créé. Une partie de la sortie d'état log4j2 est ci-dessous:

13-02-2013 15: 36: 37,574 DEBUG Appel de createAppender sur la classe org.Apache.logging.log4j.core.appender.FileAppender pour l'élément Fichier avec params (fileName = "$ {sys: logFilename}", append = "null" , lock = "null", name = "MyFile", immediateFlush = "null", suppressExceptions = "null", bufferedIO = "null", PatternLayout (% - 4r% d {aaaa-MM-jj/HH: mm: ss .SSS/zzz} [% t]% -5level% logger {36} -% msg% n), null)

13-02-2013 15: 36: 37,576 DEBUG Démarrage de FileManager $ {sys: logFilename}

Comment puis-je définir la valeur de "fileName" dans File Appender au moment de l'exécution? Alternativement, comment puis-je simplement ajouter un nouveau File Appender à l'enregistreur racine au moment de l'exécution? Dans Log4j 2.0, la plupart des API pour modifier la configuration sont masquées.

41
user84756

h/t rgoers Le FileAppender ne prend pas en charge deux signes dollar sur le nom du fichier car le fichier est ouvert au démarrage de l'appender. Ce que vous indiquez avec deux signes dollar, c'est que vous voulez - potentiellement - un nom de fichier différent pour chaque événement.

Avec un seul $ (comme dans ${sys:logFilename}), le système recherchera la propriété "logFilename" dans les propriétés du système.

Ainsi, le log4j2.xml devrait avoir:

<appenders>
    <File name="MyFile" fileName="${sys:logFilename}">
        <PatternLayout pattern="%-4r %d{${datestamp}} [%t] %-5level %logger{36} - %msg%n"/>
    </File>
</appenders>

L'application Java doit définir la propriété système:

System.setProperty("logFilename", filename);

et reconfigurer l'enregistreur:

org.Apache.logging.log4j.core.LoggerContext ctx =
    (org.Apache.logging.log4j.core.LoggerContext) LogManager.getContext(false);
ctx.reconfigure();

Cela produit le comportement souhaité.

46
user84756

Depuis la version log4j2 2.5 voici le moyen le plus simple d'y parvenir:

Dans votre log4j2.xml:

<Appenders>
   <File name="MyFile" filename="${sys:logFilename}">
   ...

En vous principal MyApp.Java fichier:

public class MyApp {

    Logger log;

    static {
          System.setProperty("logFilename", ...);
          log = LogManager.getLogger();
    }

    public static void main(String... args) {...}
}

CATCH: Vous devez définir la propriété système logFilename avant le chargement de log4j2. Dans cet exemple, avant d'appeler LogManager.getLogger.

8
Alex Yursha

Je sais que ce sujet est ancien, mais les réponses ne me convenaient pas vraiment. Voici une fonction qui vous permet de reconfigurer un Appender existant au moment de l'exécution:

static void updateLogger(String file_name, String appender_name, String package_name){
LoggerContext context = (LoggerContext) LogManager.getContext(false);
    Configuration configuration = context.getConfiguration();
    Layout<? extends Serializable> old_layout = configuration.getAppender(appender_name).getLayout();

    //delete old appender/logger
    configuration.getAppender(appender_name).stop();
    configuration.removeLogger(package_name);

    //create new appender/logger
    LoggerConfig loggerConfig = new LoggerConfig(package_name, Level.INFO, false);
    FileAppender appender = FileAppender.createAppender(file_name, "false", "false", appender_name, "true", "true", "true",
            "8192", old_layout, null, "false", "", configuration);
    appender.start();
    loggerConfig.addAppender(appender, Level.INFO, null);
    configuration.addLogger(package_name, loggerConfig);

    context.updateLoggers();
}

Vous pouvez spécifier un nom de fichier, le nom de votre appender et le nom du package que vous souhaitez enregistrer.

Exemple d'enregistreur:

<File name="fileWriter_api" fileName="${LOG_DIR}/api.log" append="false">
  <PatternLayout pattern="${PATTERN}"/>
</File>

Peut être reconfiguré en appelant comme ceci:

updateLogger("log/api_new.log", "fileWriter_api", "my.package");
8
Christian Ammann