2011-10-19 15 views
29

Sto usando logback, e sto cercando di impostare il nome del file di registro a livello di codice nel mio programma Java (simile a Setting Logback Appender path programmatically), e ho cercato di adattare tale soluzione come segue:Logback - insieme il nome del file di registro di programmazione

in logback-test.xml:

<appender name="FILE" class="ch.qos.logback.core.FileAppender"> 
    <file>log/${log_file_name}.log</file> 
    ... 

e poi di nuovo nel mio programma Java:

String logFileName = "" + System.currentTimeMillis(); // just for example 
System.setProperty("log_file_name", logFileName); 

LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); 
ContextInitializer ci = new ContextInitializer(lc); 
lc.reset(); 
try 
{ 
    // I prefer autoConfig() over JoranConfigurator.doConfigure() so I 
    // wouldn't need to find the file myself. 
    ci.autoConfig(); 
} 
catch (JoranException e) 
{ 
    // StatusPrinter will try to log this 
    e.printStackTrace(); 
} 
StatusPrinter.printInCaseOfErrorsOrWarnings(lc); 

Tuttavia il risultato è di due tronchi, uno pieno e nominato come avrei voluto, per esempio, "131904 1145343.log ", e l'altro è vuoto e denominato" log_file_name_IS_UNDEFINED.log ". Come posso impedire che questo altro file di registro vuoto venga creato?

+0

L'unico problema del codice sembra essere l'impostazione di 'System.setProperty (" log_file_name ", logFileName);' troppo tardi. Eseguilo prima che l'autoconfig di Logback sia stato eseguito e tu abbia quello che vuoi. – Robert

+0

In realtà può essere fatto molto più facilmente che nel tuo snippet di codice: http://stackoverflow.com/a/21886071/709537 –

risposta

30

Credo che quanto segue sia più vicino a ciò che si desidera.

import ch.qos.logback.classic.Logger; 
import ch.qos.logback.classic.encoder.PatternLayoutEncoder; 
import ch.qos.logback.core.FileAppender; 
import ch.qos.logback.core.util.StatusPrinter; 
import org.slf4j.LoggerFactory; 
import ch.qos.logback.classic.LoggerContext; 

public class Main { 
    public static void main(String[] args) { 
    LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); 

    FileAppender fileAppender = new FileAppender(); 
    fileAppender.setContext(loggerContext); 
    fileAppender.setName("timestamp"); 
    // set the file name 
    fileAppender.setFile("log/" + System.currentTimeMillis()+".log"); 

    PatternLayoutEncoder encoder = new PatternLayoutEncoder(); 
    encoder.setContext(loggerContext); 
    encoder.setPattern("%r %thread %level - %msg%n"); 
    encoder.start(); 

    fileAppender.setEncoder(encoder); 
    fileAppender.start(); 

    // attach the rolling file appender to the logger of your choice 
    Logger logbackLogger = loggerContext.getLogger("Main"); 
    logbackLogger.addAppender(fileAppender); 

    // OPTIONAL: print logback internal status messages 
    StatusPrinter.print(loggerContext); 

    // log something 
    logbackLogger.debug("hello"); 
    } 
} 

Se tutto ciò che serve è quello di aggiungere un timestamp del nome del file di registro, logback già supports the timestamp element. Quindi, in realtà non hai bisogno di alcun codice personalizzato.

+0

grazie per il tuo aiuto, darò questa prova. (Stavo solo usando un timestamp come esempio, il nome file effettivo sarebbe diverso) – conorsomahony

+0

Grazie, funziona - in logback-test.xml Non sto più specificando un file appender e nel codice java ne sto creando uno e allegando al logger 'root'. – conorsomahony

+3

Non è il punto di slf4j per evitare di importare ch.qos.logback.classic.Logger – Zombies

4

Sembra che il logger sia inizializzato due volte. La prima volta, probabilmente quando l'app viene caricata e non è stato possibile risolvere lo ${log_file_name}. Se si avvia l'applicazione con -Dlog_file_name=*something* è possibile verificare questo comportamento se viene creato un altro file di registro con il nome

+0

Cosa potresti fare per impostare a livello di codice il nome del file è quello di creare un'istanza di un file appender con la configurazione richiesta (nome, categoria, pacchetto, ecc.) e aggiungerlo alla gerarchia dell'appender. – srkavin

+0

Grazie, ho aggiunto esattamente '-Dlog_file_name = verify' agli argomenti VM, e in effetti ho ottenuto un log vuoto chiamato" verify.log "- C'è un modo per fermare il logger che inizia due volte? – conorsomahony

8

Ecco cosa si può fare per ignorare questi file creation.Below in più è il file di configurazione

<configuration> 
<appender name="FILE" class="ch.qos.logback.core.FileAppender"> 
<!-- "application-name" is a variable --> 
<File>c:/logs/${application-name}.log</File> 
<layout class="ch.qos.logback.classic.PatternLayout"> 
<Pattern>%d %p %t %c - %m%n</Pattern> 
</layout> 
</appender> 
<root level="debug"> 
<appender-ref ref="FILE"/> 
</root> 
</configuration> 

Ecco la parte java,

LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); 
JoranConfigurator jc = new JoranConfigurator(); 
jc.setContext(context); 
context.reset(); // override default configuration 
// inject the name of the current application as "application-name" 
// property of the LoggerContext 
context.putProperty("application-name", NAME_OF_CURRENT_APPLICATION); 
jc.doConfigure("/path/to/the/above/configuration/file.xml"); 

ho ricevuto questo da qui http://logback.qos.ch/faq.html#sharedConfiguration

+0

Un altro modo che puoi fare è inizializzare tutte le variabili di sistema prima di richiamare Logger. Funziona anche così. –

+0

Terminato utilizzando System.setProperty (..) anziché reimpostare il contesto. Sembra più pulito per me. Grazie per l'es. –

+0

Sfortunatamente l'utilizzo delle proprietà di sistema non può funzionare quando si desidera condividere la configurazione – Brice

10

Per separare/setacciare i messaggi di registro in file diversi a seconda di un attributo di runtime, è possibile utilizzare ch.qos.logback.classic.sift.SiftingAppender.

In poche parole, questo permette di impostare un FileAppender (o qualsiasi altro appender) con <file>${userid}.log</file> dove ${userId} è sostituito basa sulla MDC (Mapped Diagnostic Context) (ad esempio, MDC.put("userid", "Alice");). Vedi il primo link per l'esempio completo.

Problemi correlati