在某些情况下,我需要立即强制在对数文件夹中刷新.我在
docs发现这个选项是默认启用的.神秘地这不行.正如我在源代码中所看到的那样,正确的是BufferedOutputSream. BufferedOutputSream.flush()有什么问题吗?这可能与潮红的问题有关.
更新:
我在Windows XP Pro SP 3和Red Hat Enterprise Linux Server 5.3版(Tikanga)上发现了这个问题.
我使用这些库:
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>
更新:
我会提供一个单元测试,但似乎并不那么简单.
让我更清楚地描述这个问题.
>记录事件发生
>事件被传递到文件追加器
>事件被定义的模式序列化
>事件的序列化消息传递给文件追加器
即将写出输出流
>写入流完成,输出流被刷新(我已经
检查实施).注意immidiateFlush是真的
默认情况下,方法flush()被明确调用
>文件中没有结果!
稍后当一些底层缓冲区流动时,文件中出现事件.
所以问题是:输出流保证即时刷新?
说实话,我已经通过实现我自己的ImmediateRollingFileAppender来解决这个问题,它使用FileDescriptor的即时同步功能.有兴趣的人可以按照this.
所以这不是一个logback问题.
解决方法
我决定把我的解决方案带给大家.
首先让我澄清一点,这不是一个logback问题,而是一个JRE问题.这在 javadoc中描述,一般不应该是一个问题,直到你面对一些旧的学校集成解决方案通过文件同步.
首先让我澄清一点,这不是一个logback问题,而是一个JRE问题.这在 javadoc中描述,一般不应该是一个问题,直到你面对一些旧的学校集成解决方案通过文件同步.
所以这是一个实现立即刷新的logback appender:
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); } }
这是相应的输出流实用类.因为原来的ResilientOutputStreamBase的一些方法和领域,原本应该是扩展,最初有打包的访问修饰符,我不得不扩展OutputStream,只需将ResilientOutputStreamBase和ResilientFileOutputStream的其余部分和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); } } } }
最后配置:
<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>