[logback-dev] [JIRA] Updated: (LBCORE-143) ConsoleAppender should always write to current System.out / System.err. The underlying outputstream should not be bind statically.

Rü (JIRA) noreply-jira at qos.ch
Wed Mar 17 17:54:16 CET 2010


     [ http://jira.qos.ch/browse/LBCORE-143?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Rü updated LBCORE-143:
----------------------

    Attachment: patch

> ConsoleAppender should always write to current System.out / System.err. The underlying outputstream should not be bind statically.
> ----------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: LBCORE-143
>                 URL: http://jira.qos.ch/browse/LBCORE-143
>             Project: logback-core
>          Issue Type: Bug
>          Components: Appender
>    Affects Versions: 0.9.18
>            Reporter: tomliliu
>            Assignee: Logback dev list
>             Fix For: 0.9.19
>
>         Attachments: ConsoleAppender.java, patch
>
>
> Hi logback-dev,
> ConsoleAppender does not work nicely with JUnit.
> Symptom: when running junit tests with logback (default configuration, no logback configuration is provided), only the first test case's output was captured, the subsequent test cases' output were not captured by junit.
> The problem is that console appender binds itself to stdout / stderr statically.
> Illustrate what happens:
> Junit run test 1 -> System.out is set to test1.out -> Logback auto configure -> Console appender is bind to System.out, which is test1.out
> Junit run test 2 -> System.out is set to test2.out -> Console appender is still bind to test1.out -> The output of subsequent test cases are not correctly redirected.
> The ConsoleAppender's behavior is not correct as it should always write to current System.out / System.err.
> I worked out a simple fix and hope it will be useful:
> /**
>  * Logback: the generic, reliable, fast and flexible logging framework.
>  * 
>  * Copyright (C) 2000-2009, QOS.ch
>  * 
>  * This library is free software, you can redistribute it and/or modify it under
>  * the terms of the GNU Lesser General Public License as published by the Free
>  * Software Foundation.
>  */
> package ch.qos.logback.core;
> import java.io.IOException;
> import java.io.OutputStream;
> import ch.qos.logback.core.status.Status;
> import ch.qos.logback.core.status.WarnStatus;
> /**
>  * ConsoleAppender appends log events to <code>System.out</code> or <code>System.err</code> using a layout specified by
>  * the user. The default target is <code>System.out</code>.
>  * 
>  * For more information about this appender, please refer to the online manual at
>  * http://logback.qos.ch/manual/appenders.html#ConsoleAppender
>  * 
>  * @author Ceki G&uuml;lc&uuml;
>  */
> public class ConsoleAppender<E> extends WriterAppender<E> {
>     public static final String SYSTEM_OUT = "System.out";
>     public static final String SYSTEM_ERR = "System.err";
>     
>     protected String target = SYSTEM_OUT;
>     private interface OutputStreamProvider {
>         OutputStream getOutputStream();
>     }
>     
>     private static class SysoutProvider implements OutputStreamProvider {
>         @Override
>         public OutputStream getOutputStream() {
>             return System.out;
>         }
>     }
>     
>     private static class SyserrProvider implements OutputStreamProvider {
>         @Override
>         public OutputStream getOutputStream() {
>             return System.err;
>         }
>     }
>     
>     private static class WrapperOutputStream extends OutputStream {
>         
>         private final OutputStreamProvider provider;
>         WrapperOutputStream(OutputStreamProvider provider) {
>             this.provider = provider;
>         }
>         
>         @Override
>         public void write(int b) throws IOException {
>             provider.getOutputStream().write(b);
>         }
>         @Override
>         public void write(byte[] b, int off, int len) throws IOException {
>             provider.getOutputStream().write(b, off, len);
>         }
>         @Override
>         public void write(byte[] b) throws IOException {
>             provider.getOutputStream().write(b);
>         }
>         @Override
>         public void close() throws IOException {
>             provider.getOutputStream().close();
>         }
>         @Override
>         public void flush() throws IOException {
>             provider.getOutputStream().flush();
>         }
>     }
>     /**
>      * As in most logback components, the default constructor does nothing.
>      */
>     public ConsoleAppender() {
>     }
>     /**
>      * Sets the value of the <b>Target</b> option. Recognized values are "System.out" and "System.err". Any other value
>      * will be ignored.
>      */
>     public void setTarget(String value) {
>         String v = value.trim();
>         if (SYSTEM_OUT.equalsIgnoreCase(v)) {
>             target = SYSTEM_OUT;
>         } else if (SYSTEM_ERR.equalsIgnoreCase(v)) {
>             target = SYSTEM_ERR;
>         } else {
>             targetWarn(value);
>         }
>     }
>     /**
>      * Returns the current value of the <b>Target</b> property. The default value of the option is "System.out".
>      * 
>      * See also {@link #setTarget}.
>      */
>     public String getTarget() {
>         return target;
>     }
>     void targetWarn(String val) {
>         Status status = new WarnStatus("[" + val + " should be System.out or System.err.", this);
>         status.add(new WarnStatus("Using previously set target, System.out by default.", this));
>         addStatus(status);
>     }
>     public void start() {
>         if (target.equals(SYSTEM_OUT)) {
>             setWriter(createWriter(new WrapperOutputStream(new SysoutProvider())));
>         } else {
>             setWriter(createWriter(new WrapperOutputStream(new SyserrProvider())));
>         }
>         super.start();
>     }
>     /**
>      * This method overrides the parent {@link WriterAppender#closeWriter} implementation because the console stream is
>      * not ours to close.
>      */
>     protected final void closeWriter() {
>         writeFooter();
>     }
> }
>  

-- 
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