title: Is there a recommended way to get spring boot to JSON format logs with logback
body: <p>Using spring boot <code>2.1.1.RELEASE</code> one can seemingly format logs as JSON by providing a <code>logback-spring.xml</code> file as follows:</p>
  
  <p></p>
  
  <pre><code>&lt;appender name="stdout" class="ch.qos.logback.core.ConsoleAppender"&gt;
      &lt;encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"&gt;
          &lt;layout class="ch.qos.logback.contrib.json.classic.JsonLayout"&gt;
              &lt;timestampFormat&gt;yyyy-MM-dd'T'HH:mm:ss.SSSX&lt;/timestampFormat&gt;
              &lt;timestampFormatTimezoneId&gt;Etc/UTC&lt;/timestampFormatTimezoneId&gt;
              &lt;jsonFormatter class="ch.qos.logback.contrib.jackson.JacksonJsonFormatter"&gt;
                  &lt;prettyPrint&gt;true&lt;/prettyPrint&gt;
              &lt;/jsonFormatter&gt;
          &lt;/layout&gt;
      &lt;/encoder&gt;
  &lt;/appender&gt;
  
  &lt;root level="INFO"&gt;
      &lt;appender-ref ref="stdout" /&gt;
  &lt;/root&gt;
  </code></pre>
  
  <p></p>
  
  <p>and adding to the <code>pom.xml</code></p>
  
  <pre><code>&lt;dependency&gt;
              &lt;groupId&gt;ch.qos.logback.contrib&lt;/groupId&gt;
              &lt;artifactId&gt;logback-json-classic&lt;/artifactId&gt;
              &lt;version&gt;0.1.5&lt;/version&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;ch.qos.logback.contrib&lt;/groupId&gt;
              &lt;artifactId&gt;logback-jackson&lt;/artifactId&gt;
              &lt;version&gt;0.1.5&lt;/version&gt;
          &lt;/dependency&gt;
  </code></pre>
  
  <p>indeed leading to messages like:</p>
  
  <pre><code>{
    "timestamp" : "2018-12-11T18:20:25.641Z",
    "level" : "INFO",
    "thread" : "main",
    "logger" : "com.netflix.config.sources.URLConfigurationSource",
    "message" : "To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath.",
    "context" : "default"
  }
  </code></pre>
  
  <h1>Why?</h1>
  
  <p>I'm trialing <a href="https://logz.io" rel="noreferrer">logz.io</a> which appears to behave more favourably when logs are JSON formatted, some o the shippers struggle with multiline logs like we see in java stack traces and when formatting in JSON it can automatically parse fields like <code>level</code> and <code>message</code> and if there is MDC data it automatically gets that.</p>
  
  <p>I had some not so great experiences with a few of the methods of shipping logs to logzio, like their docker image and using rsyslog without using JSON formatted log messages.</p>
  
  <h1>Issues With This Approach</h1>
  
  <p>It works ok for console appending, but spring boot provides like <code>logging.file=test.log</code>, <code>logging.level.com.example=WARN</code>, <code>logging.pattern.console</code>. I can indeed import the managed configuration from <code>spring-boot-2.1.1.RELEASE.jar!/org/springframework/boot/logging/logback/base.xml</code> which in turn imports a <code>console-appender.xml and</code>file-appender.xml`.</p>
  
  <h2>An example of the console-appender</h2>
  
  <pre><code>&lt;included&gt;
      &lt;appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"&gt;
          &lt;encoder&gt;
              &lt;pattern&gt;${CONSOLE_LOG_PATTERN}&lt;/pattern&gt;
          &lt;/encoder&gt;
      &lt;/appender&gt;
  &lt;/included&gt;
  </code></pre>
  
  <h2>An example of the file appender</h2>
  
  <pre><code>&lt;included&gt;
      &lt;appender name="FILE"
          class="ch.qos.logback.core.rolling.RollingFileAppender"&gt;
          &lt;encoder&gt;
              &lt;pattern&gt;${FILE_LOG_PATTERN}&lt;/pattern&gt;
          &lt;/encoder&gt;
          &lt;file&gt;${LOG_FILE}&lt;/file&gt;
          &lt;rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"&gt;
              &lt;fileNamePattern&gt;${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz&lt;/fileNamePattern&gt;
              &lt;maxFileSize&gt;${LOG_FILE_MAX_SIZE:-10MB}&lt;/maxFileSize&gt;
              &lt;maxHistory&gt;${LOG_FILE_MAX_HISTORY:-0}&lt;/maxHistory&gt;
          &lt;/rollingPolicy&gt;
      &lt;/appender&gt;
  &lt;/included&gt;
  </code></pre>
  
  <p>These two are exactly what I need to support spring configuration of the properties, but they don't include the encoder/layout I'd need. </p>
  
  <p>It appears in my initial tests that I can't simple name my appender the same as those and provide my layouts. For example:</p>
  
  <pre><code>&lt;configuration&gt;
  
      &lt;include resource="org/springframework/boot/logging/logback/base.xml"/&gt;
  
      &lt;appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"&gt;
          &lt;encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"&gt;
              &lt;layout class="ch.qos.logback.contrib.json.classic.JsonLayout"&gt;
                  &lt;timestampFormat&gt;yyyy-MM-dd'T'HH:mm:ss.SSSX&lt;/timestampFormat&gt;
                  &lt;timestampFormatTimezoneId&gt;Etc/UTC&lt;/timestampFormatTimezoneId&gt;
                  &lt;jsonFormatter class="ch.qos.logback.contrib.jackson.JacksonJsonFormatter"&gt;
                      &lt;prettyPrint&gt;true&lt;/prettyPrint&gt;
                  &lt;/jsonFormatter&gt;
              &lt;/layout&gt;
          &lt;/encoder&gt;
      &lt;/appender&gt;
  
  
  
      &lt;root level="INFO"&gt;
          &lt;appender-ref ref="CONSOLE" /&gt;
      &lt;/root&gt;
  &lt;/configuration&gt;
  </code></pre>
  
  <p>leads to the message being logged in both JSON and plain text format.</p>
  
  <p>I can indeed just copy and paste the contents of these 3 files into my custom config rather than import them at all. Then I may override what I want to customise.</p>
  
  <p>However, as spring evolves and new releases are made which may add features, I'd be forever forcing myself to keep up, copy and paste the new files and make my changes and test them.</p>
  
  <p>Is there any better way that I can either:</p>
  
  <ul>
  <li>Just make additive changes to the appenders rather than entirely redefine them, e.g. keep the config from spring but provide my own encoder or layout to be used by those appenders.</li>
  <li>Configure spring to JSON log via properties entirely without any config - I doubt this :S</li>
  </ul>
  
  <hr>
  
  <p>Footnote: logzio do provide <a href="https://app.logz.io/#/dashboard/data-sources/Java--logbackappender" rel="noreferrer">a dependency</a> one can import, but I dislike the idea of coupling the logging provider into the code directly. I feel that if the servoce happens to produce JSON logs to stdout or a file, it's easy for any provider to process those and ship them to some destination. </p>