[logback-dev] [JIRA] Commented: (LBCORE-45) introduce FlushableAppender

Michael Franz (JIRA) noreply-jira at qos.ch
Mon Mar 9 10:59:11 CET 2009


    [ http://jira.qos.ch/browse/LBCORE-45?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=11072#action_11072 ] 

Michael Franz commented on LBCORE-45:
-------------------------------------

Hello Ceki,

if I understand you correctly you mean: the WirterAppender calls the FlushingPolicy after appending a log message and you are seeing two alternatives for the task of the policy:
 1. return a boolean if the Appender should perform flush
 2. pass the writer or stream so that the policy can perform the flush?
 
Although there seem to be some nice use case (like flushing after error and buffering for debug messages) both cases do not fit well into my scenario with a long running appliation where it is not guaranteed that after a message without a flush, a message triggering a flush is really passed to the appender because of the possibility for dynamic changes of the working logging configuration.
Currently I have a thread that every 30 seconds calls a flush for all buffering WriterAppenders (thanks to Java reflection). Ok with the second approach I could store the streams for flushing within the next 30 seconds, but I would have concerns about the posibility that the appender can close those streams in the meantime or that there might by some other concurrency conflicts, because the actual implementation for the stream is controlled by the appender only.

Also your example with the FLUSH marker really sounds like a workaround, since it can't be the task of a log message to control the behaviour of the logging system.



> introduce FlushableAppender
> ---------------------------
>
>                 Key: LBCORE-45
>                 URL: http://jira.qos.ch/browse/LBCORE-45
>             Project: logback-core
>          Issue Type: Improvement
>          Components: Appender
>    Affects Versions: unspecified
>         Environment: Operating System: Linux
> Platform: PC
>            Reporter: Bruno Navert
>            Assignee: Ceki Gulcu
>            Priority: Minor
>
> Suggest a new sub-interface of Appender:
> public interface FlushableAppender<E> extends Appender<E>, java.io.Flushable
> {
> }
> Then, WriterAppender could be defined to implement FlushableAppender, with this simple implementation:
>     public void flush() throws IOException
>     {
>         writer.flush();
>     }
> This would allow manual flushing of the appenders. This is particularly useful when buffered IO is used, obviously. It allows, for instance, to manually flush all appenders when a request has been fully processed, ensuring that we retain the benefits of buffered IO while also having the full logs after request processing.
> Here's sample code I used to get all appenders (run once after Logback configuration):
>     public static Set<Appender> getAllAppenders()
>     {
>         ContextSelector selector = StaticLoggerBinder.SINGLETON.getContextSelector();
>         LoggerContext loggerContext = selector.getLoggerContext();
>         Map<String, Appender> appenders = newHashMap();
>         // loop through all Loggers
>         for ( Logger logger : loggerContext.getLoggerList() )
>         {
>             // for each logger, loop through all its appenders
>             Iterator iter = logger.iteratorForAppenders();
>             while ( iter.hasNext() )
>             {
>                 // appenders are uniquely identified by name, so store them in the Map thus
>                 // this will overwrite the same entry in the Map many times (with the same reference)
>                 Appender appender = ( Appender ) iter.next();
>                 appenders.put( appender.getName(), appender );
>             }
>         }
>         return newHashSet( appenders.values() );
>     }
> The below bean is used in Spring, calling flush() forces all appenders to be flushed:
> public class LogbackFlushBean implements Flushable
> {
>     protected final Logger log = LoggerFactory.getLogger( getClass() );
>     private final Collection<FlushableAppender> flushableAppenders = newLinkedList();
>     @PostConstruct
>     public void loadFlushableAppenders()
>     {
>         for ( Appender appender : LogbackConfigurer.getAllAppenders() )
>         {
>             if ( appender instanceof FlushableAppender )
>             {
>                 flushableAppenders.add( ( FlushableAppender ) appender );
>             }
>             else
>             {
>                 log.debug( "appender {} is not Flushable, skipping", appender.getName() );
>             }
>         }
>     }
>     public void flush() throws IOException
>     {
>         for ( FlushableAppender appender : flushableAppenders )
>         {
>             log.debug( "flushing appender {}", appender.getName() );
>             appender.flush();
>         }
>     }
> }

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        


More information about the logback-dev mailing list