SLF4J/LogbackでJSON形式のログ出力

# はじめに
Fluentd の in_tail プラグインでログファイルを読み込む際に、
特別な形式ではないフォーマットだと正規表現を駆使して頑張る必要がありますが
JSON形式でログを出力してしまえばそんな手間も無くなります。
（grepビリティは低いですが・・・）

# 依存ライブラリの定義
バージョンは現時点で最新のものを埋め込んでいます。

Mavenを使っている場合

```xml:pom.xml
<dependencies>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.12</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-core</artifactId>
        <version>1.1.3</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.1.3</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback.contrib</groupId>
        <artifactId>logback-json-core</artifactId>
        <version>0.1.2</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback.contrib</groupId>
        <artifactId>logback-json-classic</artifactId>
        <version>0.1.2</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback.contrib</groupId>
        <artifactId>logback-jackson</artifactId>
        <version>0.1.2</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.5.2</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.5.2</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.5.2</version>
    </dependency>
</dependencies>
```

SBTを使っている場合

```scala:build.sbt
libraryDependencies ++= Seq(
  "org.slf4j" % "slf4j-api" % "1.7.12",
  "ch.qos.logback" % "logback-core" % "1.1.3",
  "ch.qos.logback" % "logback-classic" % "1.1.3",
  "ch.qos.logback.contrib" % "logback-json-core" % "0.1.2",
  "ch.qos.logback.contrib" % "logback-json-classic" % "0.1.2",
  "ch.qos.logback.contrib" % "logback-jackson" % "0.1.2",
  "com.fasterxml.jackson.core" % "jackson-core" % "2.5.2",
  "com.fasterxml.jackson.core" % "jackson-databind" % "2.5.2",
  "com.fasterxml.jackson.core" % "jackson-annotations" % "2.5.2"
)
```

## 補足1
Jackson2 を使うには logback-jackson 0.1.2 を使う必要があります。
logback-jackson 0.1.1 は Jackson1 に依存しています。
Jackson1 と Jackson2 はネームスペースが異なります。

## 補足2
logback-json-classic 0.1.2 は `org.slf4j.Marker` に対応していないため
出力するJSONには含まれません。
MDCなどは普通に使えます。

## 補足3
jackson-annotations は不要かもしれません（未確認）


# logback.xml の定義

```xml:logback.xml
<property name="MONITORING_LOG" value="${LOG_DIR}/monitoring.log" />
<appender name="FILE_MONITORING" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${MONITORING_LOG}</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <fileNamePattern>${MONITORING_LOG}.%d.gz</fileNamePattern>
        <maxHistory>14</maxHistory>
    </rollingPolicy>
    <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
        <layout class="ch.qos.logback.contrib.json.classic.JsonLayout">
            <jsonFormatter class="ch.qos.logback.contrib.jackson.JacksonJsonFormatter">
                <!-- <prettyPrint>true</prettyPrint> -->
            </jsonFormatter>
            <timestampFormat>yyyy-MM-dd'T'HH:mm:ss.SSSXXX</timestampFormat>
            <includeContextName>false</includeContextName>
            <appendLineSeparator>true</appendLineSeparator>
        </layout>
        <charset>UTF-8</charset>
    </encoder>
</appender>

<root level="INFO">
    <appender-ref ref="FILE_MONITORING" />
</root>
```

## 補足4
タイムスタンプのフォーマットで使っている XXX は JDK7 から使用可能です。

## 補足5
細かいオプションについては下記を見ると大体分かるはずです。
https://github.com/qos-ch/logback-contrib/blob/2161638c59572c33e76220306ac4b6fbbf863776/json/core/src/main/java/ch/qos/logback/contrib/json/JsonLayoutBase.java
https://github.com/qos-ch/logback-contrib/blob/2161638c59572c33e76220306ac4b6fbbf863776/json/classic/src/main/java/ch/qos/logback/contrib/json/classic/JsonLayout.java
https://github.com/qos-ch/logback-contrib/blob/2161638c59572c33e76220306ac4b6fbbf863776/jackson/src/main/java/ch/qos/logback/contrib/jackson/JacksonJsonFormatter.java


# ログ
出力結果は下記のようになります。
文字列内の改行文字などは \n で出力されるため、1つのログエントリにつき1行になります。

```json:monitoring.log
{"timestamp":"2015-04-05T14:45:28.481+09:00","level":"WARN","thread":"pool-1-thread-1-ScalaTest-running-SQSHelperSpec","logger":"helpers.aws.sqs.SQSHelperSpec","message":"com.amazonaws.AmazonClientException: Unable to load AWS credentials from any provider in the chain"}
{"timestamp":"2015-04-05T14:45:31.526+09:00","level":"WARN","thread":"pool-1-thread-1-ScalaTest-running-SQSHelperSpec","logger":"helpers.aws.sqs.SQSHelperSpec","message":"com.amazonaws.AmazonClientException: Unable to load AWS credentials from any provider in the chain"}
{"timestamp":"2015-04-05T14:45:31.775+09:00","level":"WARN","thread":"pool-1-thread-1-ScalaTest-running-SQSHelperSpec","logger":"helpers.aws.sqs.SQSHelperSpec","message":"com.amazonaws.AmazonClientException: Unable to load AWS credentials from any provider in the chain"}
{"timestamp":"2015-04-05T14:45:31.864+09:00","level":"WARN","thread":"pool-1-thread-1-ScalaTest-running-SQSHelperSpec","logger":"helpers.aws.sqs.SQSHelperSpec","message":"com.amazonaws.AmazonClientException: Unable to load AWS credentials from any provider in the chain"}
```