2013-06-04 3 views
42

कॉन्फ़िगर मैं एक logback appender logback.xml में परिभाषित किया गया है, यह एक डीबी appender है, लेकिन मैं उत्सुक हूँ अगर वहाँ अपने ही कनेक्शन पूल एक सेम के रूप में परिभाषित का उपयोग कर जावा में appender कॉन्फ़िगर करने के लिए किसी भी तरह से है।प्रोग्राम LogBack appender

मैं इसी तरह की चीजों को खोजने, लेकिन कभी वास्तविक जवाब।

उत्तर

87

यहाँ एक सरल उदाहरण है कि मेरे लिए काम करता (ध्यान दें कि मैं इस उदाहरण में FileAppender का उपयोग)

import org.slf4j.LoggerFactory; 

import ch.qos.logback.classic.Level; 
import ch.qos.logback.classic.Logger; 
import ch.qos.logback.classic.LoggerContext; 
import ch.qos.logback.classic.encoder.PatternLayoutEncoder; 
import ch.qos.logback.classic.spi.ILoggingEvent; 
import ch.qos.logback.core.FileAppender; 

public class Loggerutils { 

    public static void main(String[] args) { 
      Logger foo = createLoggerFor("foo", "foo.log"); 
      Logger bar = createLoggerFor("bar", "bar.log"); 
      foo.info("test"); 
      bar.info("bar"); 
    } 

    private static Logger createLoggerFor(String string, String file) { 
      LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); 
      PatternLayoutEncoder ple = new PatternLayoutEncoder(); 

      ple.setPattern("%date %level [%thread] %logger{10} [%file:%line] %msg%n"); 
      ple.setContext(lc); 
      ple.start(); 
      FileAppender<ILoggingEvent> fileAppender = new FileAppender<ILoggingEvent>(); 
      fileAppender.setFile(file); 
      fileAppender.setEncoder(ple); 
      fileAppender.setContext(lc); 
      fileAppender.start(); 

      Logger logger = (Logger) LoggerFactory.getLogger(string); 
      logger.addAppender(fileAppender); 
      logger.setLevel(Level.DEBUG); 
      logger.setAdditive(false); /* set to true if root should log too */ 

      return logger; 
    } 

} 
+0

@Andrew स्वान: क्या आप टिप्पणी में नोट कर सकते हैं कि आप वर्तमान संस्करण के साथ क्या बदलना चाहते हैं। मैं तदनुसार इसे अद्यतन करने की कोशिश करूंगा। – reto

+0

@reto मेरा परिवर्तन मुख्य रूप से (1) वर्ग घोषणा को जोड़ता है ताकि यह संकलित हो और (2) गायब "जी" को "लॉगर" में जोड़ता है। –

+1

इनपुट के लिए धन्यवाद। मैंने इन चीजों को अपडेट किया है। – reto

14

आप appenders प्रोग्राम के रूप में कॉन्फ़िगर कर सकते हैं। लगभग सभी परिशिष्ट प्रोग्रामेटिक कॉन्फ़िगरेशन का उपयोग करके परीक्षण किए जाते हैं। यह इस प्रकार है कि लॉगबैक प्रोजेक्ट स्रोत कोड में प्रोग्रामेटिक एपेंडर कॉन्फ़िगरेशन के कई उदाहरण हैं। एक logback कोर appender के लिए, logback-core/src/test/java के नीचे देखें, और एक logback-क्लासिक appender के लिए logback-classic/src/test/java के नीचे देखें।

2

बस, यदि किसी कार्यक्रम संबंधी विन्यास की एक ठोस उदाहरण के लिए देख रहा होगा।

LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); 
ConsoleAppender<ILoggingEvent> appender = 
    (ConsoleAppender) lc.getLogger("appconsole").getAppender("STDOUT"); 
LayoutWrappingEncoder<ILoggingEvent> enc = 
    (LayoutWrappingEncoder<ILoggingEvent>) appender.getEncoder(); 
enc.setCharset(Charset.forName("utf-8")); 

और मेरे logback.xml:

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
    <encoder> 
     <charset>866</charset> 
     <pattern>[%level] %msg%n</pattern> 
    </encoder> 
</appender> 

<logger name="appconsole"> 
    <appender-ref ref="STDOUT" /> 
</logger> 

मैं क्यों की जरूरत है programmaticaly एक लकड़हारा कॉन्फ़िगर

यहाँ मैं सेटअप ConsoleAppender की चारसेट

? क्योंकि, मैं अपने ऐप (स्प्रिंग बूट) को एक जार फ़ाइल में पैकेजिंग करता हूं। नतीजतन Logback.xml फ़ाइल एक जार के अंदर छिपा हुआ प्रतीत होता है। हालांकि, यह अनपॅक करने और इसे बदलने के लिए सुविधाजनक नहीं है। और मैं अपने app.jar बगल में किसी भी logback.xml फ़ाइल की जरूरत नहीं है । मेरे पास केवल app.yaml फ़ाइल है जिसमें ऐप के लिए सभी कॉन्फ़िगरेशन गुण शामिल हैं।

3

एक संदर्भ के रूप में, जब आप कोड वालों बनाने के लिए जिम्मेदार संशोधित करने के लिए प्रयास करते हैं, वहाँ नियम है कि एक लकड़हारा काम करने के लिए आदेश में संतुष्ट किया जाना चाहिए का एक समूह है।

ये नियम एक महान और उपयोगी लेख Programmatic configuration of slf4j/logback में वर्णित किया गया:

अब मैं slf4j/logback के कार्यक्रम संबंधी विन्यास के साथ अनुभव है।

टास्क

एक कार्यक्रम प्रत्येक संसाधित इनपुट फ़ाइल के लिए अलग लॉग फ़ाइल को खोलने चाहिए।

कार्य

इसके बजाय एक्सएमएल के माध्यम से logback कॉन्फ़िगर करने की

के लिए समाधान, एक "मैन्युअल" का दृष्टांत को एनकोडर, appenders और वालों, तो कॉन्फ़िगर और उन्हें एक साथ लिंक की जरूरत है।

चेतावनी 1

Logback appenders के बीच एनकोडर (अर्थात PatternLayoutEncoder) साझा करने के लिए प्रयास पर पागल हो जाता है। चेतावनी 1

के लिए

समाधान प्रत्येक appender के लिए अलग एनकोडर बनाएँ।

चेतावनी 2

Logback, कुछ भी लॉग इन करने के लिए मना कर दिया है, तो एनकोडर और appenders लॉगिंग संदर्भ के साथ संबद्ध नहीं हैं।

चेतावनी 2 प्रत्येक एनकोडर और appender पर

कॉल setContext के लिए समाधान, एक पैरामीटर के रूप LoggerFactory गुजर।

चेतावनी 3

Logback, कुछ भी लॉग इन करने के लिए मना कर दिया एनकोडर और appenders शुरू नहीं कर रहे हैं। चेतावनी 3

एनकोडर और appenders के लिए

समाधान सही क्रम में शुरू किया जा करने की जरूरत है, यानी प्रथम एनकोडर, तो appenders।

चेतावनी 4

RollingPolicy वस्तुओं (अर्थात TimeBasedRollingPolicy) की तरह "तिथि मान्य नहीं", अजीब त्रुटि संदेशों का उत्पादन जब वे appender रूप में एक ही संदर्भ से जुड़ी नहीं हैं।

एनकोडर और appenders पर के रूप में RollingPolicy एक ही रास्ते पर चेतावनी 4

कॉल setContext के लिए समाधान।

यहाँ "मैन्युअल" logback विन्यास का उदाहरण काम कर रहा है:

package testpackage 

import ch.qos.logback.classic.Level 
import ch.qos.logback.classic.Logger 
import ch.qos.logback.classic.LoggerContext 
import ch.qos.logback.classic.encoder.PatternLayoutEncoder 
import ch.qos.logback.core.ConsoleAppender 
import ch.qos.logback.core.rolling.RollingFileAppender 
import ch.qos.logback.core.rolling.TimeBasedRollingPolicy 

import org.slf4j.LoggerFactory 

class TestLogConfig { 

    public static void main(String[] args) { 
    LoggerContext logCtx = LoggerFactory.getILoggerFactory() 

    PatternLayoutEncoder logEncoder = new PatternLayoutEncoder() 
    logEncoder.setContext(logCtx) 
    logEncoder.setPattern('%-12date{YYYY-MM-dd HH:mm:ss.SSS} %-5level - %msg%n') 
    logEncoder.start() 

    ConsoleAppender logConsoleAppender = new ConsoleAppender() 
    logConsoleAppender.setContext(logCtx) 
    logConsoleAppender.setName('console') 
    logConsoleAppender.setEncoder(logEncoder) 
    logConsoleAppender.start() 

    logEncoder = new PatternLayoutEncoder() 
    logEncoder.setContext(logCtx) 
    logEncoder.setPattern('%-12date{YYYY-MM-dd HH:mm:ss.SSS} %-5level - %msg%n') 
    logEncoder.start() 

    RollingFileAppender logFileAppender = new RollingFileAppender() 
    logFileAppender.setContext(logCtx) 
    logFileAppender.setName('logFile') 
    logFileAppender.setEncoder(logEncoder) 
    logFileAppender.setAppend(true) 
    logFileAppender.setFile('logs/logfile.log') 

    TimeBasedRollingPolicy logFilePolicy = new TimeBasedRollingPolicy() 
    logFilePolicy.setContext(logCtx) 
    logFilePolicy.setParent(logFileAppender) 
    logFilePolicy.setFileNamePattern('logs/logfile-%d{yyyy-MM-dd_HH}.log') 
    logFilePolicy.setMaxHistory(7) 
    logFilePolicy.start() 

    logFileAppender.setRollingPolicy(logFilePolicy) 
    logFileAppender.start() 

    Logger log = logCtx.getLogger("Main") 
    log.additive = false 
    log.level = Level.INFO 
    log.addAppender(logConsoleAppender) 
    log.addAppender(logFileAppender) 
    } 
} 
0
नहीं

(अभी तक?) टिप्पणी करने के लिए अनुमति दी है, मैं सिर्फ तीन युक्तियों जोड़ना चाहते हैं;

  • ऊपर चेतावनियां के बारे में, यदि आप समस्या है, बस

    StatusPrinter.print(context); 
    

    के लिए एक कॉल जोड़े जाने के बाद सब कुछ, कॉन्फ़िगर किया गया है कि है, जोड़ा होने के बाद अपने appenders जड़/"मुख्य" एपेंडर: आपको बताएगा कि क्या गलत है।

  • मैं अलग फ़ाइलों में अलग प्रवेश-स्तर के लिए बहुत पसंद है; मैं त्रुटि फ़ाइल में देख रही है और इतने पर के साथ शुरू, उनकी तरह

tot_[app name].log : Level.INFO 
deb_[app name].log : Level.DEBUG 
err_[app name].log : Level.ERROR 

रूटिंग सेट

private static class ThresholdLoggerFilter extends Filter<ILoggingEvent> { 

     private final Level level; 

     private ThresholdLoggerFilter(Level level){ 
      this.level = level; 
     } 

     @Override 
     public FilterReply decide(ILoggingEvent event) { 
      if (event.getLevel().isGreaterOrEqual(level)) { 
       return FilterReply.NEUTRAL; 
      } else { 
       return FilterReply.DENY; 
      } 
     } 
    } 
के रूप में एक सरल निजी फिल्टर वर्ग इस तरह के के माध्यम से हो रही है जब त्रुटियों की तलाश में

और फिर बस myFilter.start() और myAppender.addFilter(myFilter); पर कॉल करें।

  • अंत में, यह एक साथ डाल, मैं आमतौर पर गतिशील रूप से सेटअप की तरह

    public interface LoggingService { 
        void setRootLogLevel(Level level); 
    } 
    

कुछ सरल इंटरफ़ेस को लागू कुछ संपत्ति में जड़ लॉगिंग स्तर रखते हुए होने लॉग स्तरों को बदलने में सक्षम होना चाहता हूँ -फाइल जिस पर नजर रखी जाती है ताकि जब भी वहां कुछ वैध इनपुट हो, तो मैं बस इस सेवा को

@Override 
    public void setRootLogLevel(Level level) { 
     if (context != null && context.isStarted()) { 
     ((Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME)).setLevel(level); 
     } 
    } 
मेरे नए रूट लॉगर स्तर के साथ

संबंधित मुद्दे