2012-08-06 13 views
12

फ्लश नहीं करता है कुछ परिस्थितियों के लिए मुझे तुरंत लॉगबैक के फ़ाइल एपेंडर में फ्लशिंग करने की आवश्यकता होती है। मुझे docs में मिला है यह विकल्प डिफ़ॉल्ट रूप से सक्षम है। रहस्यमय रूप से यह काम नहीं करता है। जैसा कि मैंने अंतर्निहित प्रक्रियाओं में देखा है, BufferedOutputSream सही ढंग से शामिल है। BufferedOutputSream.flush() के साथ कोई समस्या है? शायद यह फ्लशिंग मुद्दे से संबंधित है।लॉगबैक फ़ाइल एपेंडर तुरंत

अद्यतन: मुझे Windows XP Pro SP 3 पर और Red Hat Enterprise Linux सर्वर रिलीज 5.3 (टिकंगा) पर समस्या मिली। मैं इन libs इस्तेमाल किया:

jcl-over-slf4j-1.6.6.jar 
logback-classic-1.0.6.jar 
logback-core-1.0.6.jar 
slf4j-api-1.6.6.jar 

logback.xml है:

<configuration> 
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> 
     <file>/somepath/file.log</file> 
     <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> 
      <fileNamePattern>file.log.%i</fileNamePattern> 
      <minIndex>1</minIndex> 
      <maxIndex>3</maxIndex> 
     </rollingPolicy> 
     <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> 
      <maxFileSize>5MB</maxFileSize> 
     </triggeringPolicy> 
     <encoder> 
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern> 
     </encoder> 
    </appender> 

    <root level="debug"> 
     <appender-ref ref="FILE"/> 
    </root> 
</configuration> 

अपडेट किया गया: मैं एक इकाई परीक्षण उपलब्ध कराएंगे लेकिन यह इतना आसान नहीं लगता है। मुझे इस मुद्दे का अधिक स्पष्ट रूप से वर्णन करने दें। प्रवेश की

  1. घटना हुई
  2. घटना फ़ाइल appender में पारित हो जाता
  3. घटना परिभाषित पैटर्न के साथ धारावाहिक है
  4. घटना के धारावाहिक संदेश फ़ाइल appender के लिए पारित किया और के बारे में उत्पादन करने के लिए लिखने के लिए है धारा
  5. स्ट्रीम को लिखना समाप्त हो गया है, आउटपुट स्ट्रीम फ़्लश हो गई है (मेरे पास कार्यान्वयन की जांच की गई है)। ध्यान दें कि immidiateFlush डिफ़ॉल्ट है इसलिए विधि flush() स्पष्ट रूप से
  6. फ़ाइल में कोई परिणाम नहीं है!

कुछ समय बाद जब कुछ अंतर्निहित बफर फ़ाइल में घटना प्रकट हुई थी। तो सवाल यह है: आउटपुट स्ट्रीम तत्काल फ्लश की गारंटी देता है?

ईमानदार होने के लिए मैंने अपने स्वयं के ImmediateRollingFileAppender को लागू करके इसे हल कर लिया है जो तत्काल समन्वयन के FileDescriptor की सुविधा प्रदान करता है। रुचि रखने वाला कोई भी व्यक्ति this का पालन कर सकता है।

तो यह एक लॉगबैक मुद्दा नहीं है।

+1

आपने किस ऑपरेटिंग सिस्टम पर यह खोज लिया है? –

+0

अपनी लॉगबैक कॉन्फ़िगरेशन पोस्ट करें। – gresdiplitude

+0

क्या आप कृपया "रहस्यमय तरीके से यह काम नहीं करते" परिभाषित कर सकते हैं? एक इकाई परीक्षण प्रदान करना बहुत उपयोगी होगा। बीटीडब्ल्यू, जेडीके का कौन सा संस्करण आप उपयोग कर रहे हैं? – Ceki

उत्तर

8

मैंने अपने समाधान को सभी को लाने का फैसला किया। मुझे सबसे पहले यह स्पष्ट करने दें कि यह लॉगबैक समस्या नहीं है और जेआरई समस्या नहीं है। यह javadoc में वर्णित है और आम तौर पर फ़ाइल सिंकिंग पर कुछ पुराने स्कूल एकीकरण समाधान का सामना करने तक एक मुद्दा नहीं होना चाहिए।

public class ImmediateFileAppender<E> extends RollingFileAppender<E> { 

    @Override 
    public void openFile(String file_name) throws IOException { 
     synchronized (lock) { 
      File file = new File(file_name); 
      if (FileUtil.isParentDirectoryCreationRequired(file)) { 
       boolean result = FileUtil.createMissingParentDirectories(file); 
       if (!result) { 
        addError("Failed to create parent directories for [" + file.getAbsolutePath() + "]"); 
       } 
      } 

      ImmediateResilientFileOutputStream resilientFos = new ImmediateResilientFileOutputStream(file, append); 
      resilientFos.setContext(context); 
      setOutputStream(resilientFos); 
     } 
    } 

    @Override 
    protected void writeOut(E event) throws IOException { 
     super.writeOut(event); 
    } 

} 

यह आउटपुट धारा उपयोगिता वर्ग इसी जाता है:

तो यह एक logback appender तुरंत फ्लश करने के लिए लागू किया है। मूल ResilientOutputStreamBase के कुछ विधियों और फ़ील्डों के कारण जो प्रारंभ में विस्तारित होने के लिए पैक किए गए एक्सेस संशोधक हैं, मुझे इसके बजाय OutputStream का विस्तार करना था और बस बाकी को कॉपी करें और ResilientOutputStreamBase और ResilientFileOutputStream को इस नए से अपरिवर्तित करें।

public class ImmediateResilientFileOutputStream extends OutputStream { 

    // merged code from ResilientOutputStreamBase and ResilientFileOutputStream 

    protected FileOutputStream os; 

    public FileOutputStream openNewOutputStream() throws IOException { 
     return new FileOutputStream(file, true); 
    } 

    @Override 
    public void flush() { 
     if (os != null) { 
      try { 
       os.flush(); 
       os.getFD().sync(); // this's make sence 
       postSuccessfulWrite(); 
      } catch (IOException e) { 
       postIOFailure(e); 
      } 
     } 
    } 

} 

और अंत में config:: - अच्छी तरह से किया

<appender name="FOR_INTEGRATION" class="package.ImmediateFileAppender"> 
    <file>/somepath/for_integration.log</file> 
    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> 
     <fileNamePattern>for_integration.log.%i</fileNamePattern> 
     <minIndex>1</minIndex> 
     <maxIndex>3</maxIndex> 
    </rollingPolicy> 
    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> 
     <maxFileSize>5MB</maxFileSize> 
    </triggeringPolicy> 
    <encoder> 
     <pattern>%d{HH:mm:ss.SSS} - %msg%n</pattern> 
     <immediateFlush>true</immediateFlush> 
    </encoder> 
</appender> 
2

आप एक अच्छा काम किया है अभी-अभी बदली कोड प्रदर्शित करते हैं।

<encoder class="ch.qos.logback.core.recovery.ImmediateFlushPatternLayoutEncoder"> 

जांची नहीं:

public class ImmediateFlushPatternLayoutEncoder extends PatternLayoutEncoder { 
    public void doEncode(ILoggingEvent event) throws IOException { 
     super.doEncode(event); 
     if (isImmediateFlush()) { 
      if (outputStream.os instanceof FileOutputStream) { 
       ((FileOutputStream) outputStream.os).getFD().sync(); 
      } 
     } 
    } 
} 

विन्यास में, आप उस विशिष्ट encoder का उपयोग करने के लिए है: यहाँ यह अधिक संक्षिप्त प्राप्त करने के लिए एक प्रस्ताव है। शायद फ़ील्ड के साथ दृश्यता के मुद्दे होंगे, लॉगबैक ch.qos.logback.core.recovery पैकेज स्वयं का उपयोग करने की आवश्यकता है।

वैसे, मैं आपको submit a bug report पर पर अतिरिक्त विकल्प LayoutWrappingEncoder पर लॉग इन करने के लिए लॉग इन करने के लिए आमंत्रित करता हूं।

+0

धन्यवाद, मार्टिन। इन दिनों में से एक यह करेगा। हमें और परियोजना को बनाए रखने के लिए धन्यवाद। –

+2

ने एक जिरा बनाया है http://jira.qos.ch/browse/LOGBACK-735 –

+0

यह आउटपुटस्ट्रीम एक ResilientFileOutputStream है, और इसे FileOutputStream से विस्तारित नहीं किया गया है, इसलिए इसमें getFD() विधि नहीं है। – BlackJoker

0

कई मॉनिटरिंग मिडलवेयर टाइम स्टैम्प और फ़ाइल आकार के अपडेट की जांच करके नई घटनाओं को ढूंढते हैं। इस कारण से, ईवेंट को रिकॉर्ड करने की आवश्यकता है, समय टिकट और फ़ाइल का आकार अपडेट किया गया है।

इस वर्ग appender के लिए यह

public class MyFileAppender<E> extends FileAppender<E> { 
    protected void writeOut(E event) throws IOException { 
     super.writeOut(event); 
     ResilientFileOutputStream resilientFos = (ResilientFileOutputStream) super.getOutputStream(); 
     resilientFos.flush(); 
     resilientFos.getChannel().force(true); 
    } 
} 

सेट MyFileAppender वर्ग का समाधान कर सकता है।

<appender name="FILE" class="MyFileAppender"> 

मुझे उम्मीद है कि लॉगबैक इस समस्या को हल करता है।

+0

मुझे इस समाधान के साथ समस्या का सामना करना पड़ रहा है, बाधित थ्रेड के लिए "resilientFos.getChannel()। बल (सत्य)" फ़ाइल चैनल बंद कर देता है और उसके बाद लॉगिंग बंद हो जाता है। – Sushant

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