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>
