Java – the logback file appender will not be refreshed immediately
In some cases, I need to force a refresh in the log folder immediately I found in docs that this option is enabled by default Mysteriously, that won't work As I can see in the source code, the correct one is bufferedoutputsream BufferedOutputSream. Is there a problem with flush()? This may be related to the problem of flushing
Update: I found this problem on Windows XP Pro SP 3 and Red Hat Enterprise Linux server version 5.3 (Tikanga) I use these libraries:
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 is:
<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>
Update: I will provide a unit test, but it doesn't seem so simple Let me describe the problem more clearly
>Record the event occurrence > the event is passed to the file adder > the mode serialization defined by the event > the serialization message of the event is passed to the file adder, i.e. write the output stream > write the stream is completed, and the output stream is refreshed (I have checked the implementation) Note that immidiateflush is true. By default, the method flush () is explicitly called > there is no result in the file!
Later, when some of the underlying buffers flow, an event occurs in the file So the question is: does the output stream guarantee immediate refresh?
To be honest, I have solved this problem by implementing my own immediaterollingfileappender, which uses the immediate synchronization function of filedescriptor Interested people can follow this
So this is not a logback problem
Solution
I decided to bring my solution to you
Therefore, this is a logback appender for immediate refresh:
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); } }
This is the corresponding output stream utility class Because some methods and fields of the original resilientoutputstreambase should have been extended. At first, there were packaged access modifiers, so I had to extend the OutputStream, just keep the rest of the resilientoutputstreambase and resilientfileoutputstream and resilientfileoutputstream unchanged I just show the changed code:
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); } } } }
Final configuration:
<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>