title: Problems of print java exceptions in one line by logback for docker
body: <p>I am going to put my java app into docker. But based on our company's logging facility, i have to use <code>fluentd</code> to collect containers' log. That requires me to put java stacktraces into one line log.</p>
  
  <p>I did the following, it works in some circumstances but fails in one another.</p>
  
  <pre class="lang-java prettyprint-override"><code>package com.alex;
  
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  import java.util.zip.DataFormatException;
  
  public class Main {
      private static final Logger logger = LoggerFactory.getLogger(Main.class);
  
      public static void alexExc() throws Exception {
          throw new Exception("hello");
      }
  
      public static void main(String[] args) throws Exception {
          try {
              alexExc();
          } catch (Throwable t) {
              logger.error("oops", t);
          }
  
          throw new DataFormatException("invalid data format");
      }
  }
  </code></pre>
  
  <p>The following is my converter to replace the separator with my specified one "#012"</p>
  
  <pre class="lang-java prettyprint-override"><code>package com.alex;
  
  import ch.qos.logback.classic.pattern.ThrowableProxyConverter;
  import ch.qos.logback.classic.spi.IThrowableProxy;
  import ch.qos.logback.core.CoreConstants;
  
  public class OneLineStackTraceConverter extends ThrowableProxyConverter {
      protected String throwableProxyToString(IThrowableProxy tp) {
          String originalStackTrace = super.throwableProxyToString(tp);
  
          return originalStackTrace.replace(CoreConstants.LINE_SEPARATOR, " #012");
      }
  }
  </code></pre>
  
  <p>And then is my logback configuration:</p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
  &lt;configuration scan="true" scanPeriod="30 seconds"&gt;
      &lt;conversionRule  conversionWord="ex"
              converterClass="com.alex.OneLineStackTraceConverter" /&gt;
  
      &lt;appender name="INFO_FILE"
                class="ch.qos.logback.core.rolling.RollingFileAppender"&gt;
          &lt;file&gt;/logs/loggingmdc/info.log&lt;/file&gt;
          &lt;rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"&gt;
              &lt;fileNamePattern&gt;/logs/loggingmdc/info.log.%i&lt;/fileNamePattern&gt;
              &lt;minIndex&gt;1&lt;/minIndex&gt;
              &lt;maxIndex&gt;5&lt;/maxIndex&gt;
          &lt;/rollingPolicy&gt;
          &lt;triggeringPolicy
                  class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"&gt;
              &lt;maxFileSize&gt;1GB&lt;/maxFileSize&gt;
          &lt;/triggeringPolicy&gt;
          &lt;encoder&gt;
              &lt;pattern&gt;%d{yyyy-MM-dd HH:mm:ss.SSS} %le %logger{0}: ## %msg\n&lt;/pattern&gt;
          &lt;/encoder&gt;
          &lt;filter class="ch.qos.logback.classic.filter.LevelFilter"&gt;
              &lt;level&gt;INFO&lt;/level&gt;
              &lt;onMatch&gt;ACCEPT&lt;/onMatch&gt;
              &lt;onMismatch&gt;DENY&lt;/onMismatch&gt;
          &lt;/filter&gt;
      &lt;/appender&gt;
      &lt;appender name="DEBUG_FILE"
                class="ch.qos.logback.core.rolling.RollingFileAppender"&gt;
          &lt;file&gt;/logs/loggingmdc/debug.log&lt;/file&gt;
          &lt;rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"&gt;
              &lt;fileNamePattern&gt;/logs/loggingmdc/debug.log.%i&lt;/fileNamePattern&gt;
              &lt;minIndex&gt;1&lt;/minIndex&gt;
              &lt;maxIndex&gt;5&lt;/maxIndex&gt;
          &lt;/rollingPolicy&gt;
          &lt;triggeringPolicy
                  class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"&gt;
              &lt;maxFileSize&gt;1GB&lt;/maxFileSize&gt;
          &lt;/triggeringPolicy&gt;
          &lt;encoder&gt;
              &lt;pattern&gt;%d{yyyy-MM-dd HH:mm:ss.SSS} %le %logger{0}: ## %msg %ex\n&lt;/pattern&gt;
          &lt;/encoder&gt;
          &lt;filter class="ch.qos.logback.classic.filter.LevelFilter"&gt;
              &lt;level&gt;DEBUG&lt;/level&gt;
              &lt;onMatch&gt;ACCEPT&lt;/onMatch&gt;
              &lt;onMismatch&gt;DENY&lt;/onMismatch&gt;
          &lt;/filter&gt;
      &lt;/appender&gt;
      &lt;appender name="ERROR_FILE"
                class="ch.qos.logback.core.rolling.RollingFileAppender"&gt;
          &lt;file&gt;/logs/loggingmdc/error.log&lt;/file&gt;
          &lt;rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"&gt;
              &lt;fileNamePattern&gt;/logs/loggingmdc/error.log.%i&lt;/fileNamePattern&gt;
              &lt;minIndex&gt;1&lt;/minIndex&gt;
              &lt;maxIndex&gt;5&lt;/maxIndex&gt;
          &lt;/rollingPolicy&gt;
          &lt;triggeringPolicy
                  class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"&gt;
              &lt;maxFileSize&gt;1GB&lt;/maxFileSize&gt;
          &lt;/triggeringPolicy&gt;
          &lt;encoder&gt;
              &lt;pattern&gt;%d{yyyy-MM-dd HH:mm:ss.SSS} %le %logger{0}: ## %msg %ex\n&lt;/pattern&gt;
          &lt;/encoder&gt;
          &lt;filter class="ch.qos.logback.classic.filter.LevelFilter"&gt;
              &lt;level&gt;ERROR&lt;/level&gt;
              &lt;onMatch&gt;ACCEPT&lt;/onMatch&gt;
              &lt;onMismatch&gt;DENY&lt;/onMismatch&gt;
          &lt;/filter&gt;
      &lt;/appender&gt;
      &lt;appender name="THIRD_PARTY_FILE"
                class="ch.qos.logback.core.rolling.RollingFileAppender"&gt;
          &lt;file&gt;/logs/loggingmdc/thirdparty.log&lt;/file&gt;
          &lt;rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"&gt;
              &lt;fileNamePattern&gt;/logs/loggingmdc/thirdparty.log.%i&lt;/fileNamePattern&gt;
              &lt;minIndex&gt;1&lt;/minIndex&gt;
              &lt;maxIndex&gt;5&lt;/maxIndex&gt;
          &lt;/rollingPolicy&gt;
          &lt;triggeringPolicy
                  class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"&gt;
              &lt;maxFileSize&gt;1GB&lt;/maxFileSize&gt;
          &lt;/triggeringPolicy&gt;
          &lt;encoder&gt;
              &lt;pattern&gt;%d{yyyy-MM-dd HH:mm:ss.SSS} %le %logger{0}: ## %msg %ex\n&lt;/pattern&gt;
          &lt;/encoder&gt;
      &lt;/appender&gt;
  
      &lt;root level="INFO"&gt;
          &lt;appender-ref ref="THIRD_PARTY_FILE"/&gt;
      &lt;/root&gt;
      &lt;logger name="com.alex" level="DEBUG" additivity="false"&gt;
          &lt;appender-ref ref="INFO_FILE"/&gt;
          &lt;appender-ref ref="DEBUG_FILE"/&gt;
          &lt;appender-ref ref="ERROR_FILE"/&gt;
      &lt;/logger&gt;
  &lt;/configuration&gt;
  </code></pre>
  
  <p>As you can see in my logback configuration, I add a <code>conversionRule</code> to specify that the exception in logging event is to use my <code>OneLineStackTraceConverter</code>.</p>
  
  <ol>
  <li>it works if I include <code>%ex</code> in each pattern for my encoder</li>
  <li>it does not work if I DONOT include <code>%ex</code> in the pattern. why? if the user forgets to include <code>%ex</code> in its pattern, do I have some other conversionWord to use for that exception?</li>
  <li>The last <code>DataFormatException</code> does not go to the log file, it comes out in the console, which I also expect it to go to logfile. How can I make it to do so ?</li>
  </ol>
  
  <p>Thanks.</p>