2010-09-27 4 views
18

Ich versuche, Logback Appender-Pfad programmgesteuert festzulegen. (RollingFileAppender mit FixedWindowRollingPolicy um genau zu sein)Logback Appender-Pfad programmgesteuert festlegen

Ich tue dies, weil ich möchte, dass meine Benutzer ermöglichen, den Protokollpfad in einem Einstellungsdialog (Eclipse RCP) zu setzen

ich so etwas wie dies versucht haben, aber ich nicht den Protokollpfad von ändern, was in der Konfigurationsdatei definiert ist:

Logger logback_logger = (ch.qos.logback.classic.Logger)LoggerFactory 
    .getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME); 
RollingFileAppender<ILoggingEvent> rfappender = 
    (RollingFileAppender<ILoggingEvent>)logback_logger.getAppender("FILE"); 
rfappender.setFile(newFile); 
FixedWindowRollingPolicy rollingPolicy = 
    (FixedWindowRollingPolicy)rfappender.getRollingPolicy(); 
rollingPolicy.setFileNamePattern(newPattern); 

Antwort

13

Eigenschaften System verwenden und die Konfigurationsdatei neu zu laden scheint sauberer:

Änderung der logback.xml Datei:

<file>${log_path:-}myfile.log</file> 
.... 
<FileNamePattern>${log_path:-}myfile.%i.log</FileNamePattern> 

Dies wird die Standardposition in das Arbeitsverzeichnis festgelegt. Dann verwenden:

System.setProperty("log_path", my_log_path); 

//Reload: 
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); 
+2

Die Verwendung des ContextInitializer ist ziemlich falsch. Siehe meine Antwort für den richtigen Ansatz. – Ceki

+1

coole Sachen! Eine Sache, die ich geändert habe: Ich benutze lc.putProperty ("log_path", my_log_path) anstelle von System.setProperty. Es sieht besser aus, da 0 Globals verwendet wurden. – Sasha

5

am Logback Code Sehen, ich habe eine Abhilfe gefunden:

rollingPolicy.stop(); 
rfappender.stop(); 
rollingPolicy.start(); 
rfappender.start(); 

Dies bewirkt, dass Logback die neuen Definitionen verwendet. Es fühlt sich jedoch immer noch wie ein Workaround an.

26

Sobald Sie programmatisch Ihre appender konfigurieren, müssen Sie die start() Methode aufrufen. Wenn der Appender Unterkomponenten hat, rufen Sie zuerst start() für die Unterkomponenten auf. Sie fügen dann den Appender dem Logger Ihrer Wahl hinzu. Hier

ein Beispiel:

import ch.qos.logback.classic.Logger; 
import ch.qos.logback.classic.encoder.PatternLayoutEncoder; 
import ch.qos.logback.core.rolling.FixedWindowRollingPolicy; 
import ch.qos.logback.core.rolling.RollingFileAppender; 
import ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy; 
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(); 

    RollingFileAppender rfAppender = new RollingFileAppender(); 
    rfAppender.setContext(loggerContext); 
    rfAppender.setFile("testFile.log"); 
    FixedWindowRollingPolicy rollingPolicy = new FixedWindowRollingPolicy(); 
    rollingPolicy.setContext(loggerContext); 
    // rolling policies need to know their parent 
    // it's one of the rare cases, where a sub-component knows about its parent 
    rollingPolicy.setParent(rfAppender); 
    rollingPolicy.setFileNamePattern("testFile.%i.log.zip"); 
    rollingPolicy.start(); 

    SizeBasedTriggeringPolicy triggeringPolicy = new ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy(); 
    triggeringPolicy.setMaxFileSize("5MB"); 
    triggeringPolicy.start(); 

    PatternLayoutEncoder encoder = new PatternLayoutEncoder(); 
    encoder.setContext(loggerContext); 
    encoder.setPattern("%-4relative [%thread] %-5level %logger{35} - %msg%n"); 
    encoder.start(); 

    rfAppender.setEncoder(encoder); 
    rfAppender.setRollingPolicy(rollingPolicy); 
    rfAppender.setTriggeringPolicy(triggeringPolicy); 

    rfAppender.start(); 

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

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

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

Der obige Code der programmatische Ausdruck der Schritte von den logback XML-Konfigurator genommen, das heißt Joran, wenn es die RollingFixedWindow.xml Datei analysiert.

+4

(Es ist ein bisschen peinlich, nicht mit Ihnen zu Protokollieren Sachen, aber) das ist nicht das, was ich versuche zu tun - Ich möchte meine Logger mit XML konfigurieren, und ändern Sie nur den Speicherort von Code. Auf diese Weise können erfahrene Benutzer feingranulare Protokollierungseigenschaften steuern, und unerfahrene Benutzer verwenden die Benutzeroberfläche. Neustarten des Appenders durch Code funktioniert; Verwenden von Systemeigenschaften und ContextInitializer funktioniert besser und weniger hart codiert, warum ist das falsch? – yshalbar

+0

Ist dieser Ansatz noch gültig mit den letzten Versionen von Logback? –

+0

Der Link zu 'RollingFixedWindow.xml' ist unterbrochen –