logbackでレベルごとに出力するファイルを分ける

## やりたいこと
運用をしていると、エラーを調査するために膨大なログの中からgrepすることが多々あります。
特に統計情報や、運用のためにInfoレベルでログに書き込んでいる情報がある場合、ログの出力数が多くなり、エラー情報をgrepするのに時間がかかることが多いです。

そんな場合には、レベルごとに出力するファイルを分けることで、grepする時間を少なくすることができます。
また分け方や運用方法によっては、監視用スクリプトの設定を容易にすることもできると思います

## やりかた
フィルターのLevelFilterを使用することで可能となります。

```xml:logger.xml
<filter class="ch.qos.logback.classic.filter.LevelFilter">
    <level>ERROR</level>
    <onMatch>ACCEPT</onMatch>
    <onMismatch>DENY</onMismatch>
</filter>

```

## 設定してみる
PlayFrameworkを使ったアプリケーションで、Trace以外のレベルごとにファイルを分けた設定例です。

```	xml:logger.xml
<configuration>

    <conversionRule conversionWord="coloredLevel" converterClass="play.api.Logger$ColoredLevel" />

    <appender name="FILE_ERROR" class="ch.qos.logback.core.FileAppender">
        <file>${application.home}/logs/error.log</file>
        <encoder>
            <pattern>%date{yyyy-MM-dd'T'HH:mm:ssZ,GMT} [%level] %logger %replace(%message){'\n', '\\n'} %replace(%xException){'\n', '\\n'}%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="FILE_INFO" class="ch.qos.logback.core.FileAppender">
        <file>${application.home}/logs/info.log</file>
        <encoder>
            <pattern>%date{yyyy-MM-dd'T'HH:mm:ssZ,GMT} [%level] %logger %replace(%message){'\n', '\\n'} %replace(%xException){'\n', '\\n'}%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="FILE_WARN" class="ch.qos.logback.core.FileAppender">
        <file>${application.home}/logs/warn.log</file>
        <encoder>
            <pattern>%date{yyyy-MM-dd'T'HH:mm:ssZ,GMT} [%level] %logger %replace(%message){'\n', '\\n'} %replace(%xException){'\n', '\\n'}%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="FILE_DEBUG" class="ch.qos.logback.core.FileAppender">
        <file>${application.home}/logs/debug.log</file>
        <encoder>
            <pattern>%date{yyyy-MM-dd'T'HH:mm:ssZ,GMT} [%level] %logger %message %xException%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%coloredLevel %logger{15} - %message%n%xException{5}</pattern>
        </encoder>
    </appender>

    <logger name="play" level="INFO" />
    <logger name="application" level="DEBUG" />

    <!-- Off these ones as they are annoying, and anyway we manage configuration ourself -->
    <logger name="com.avaje.ebean.config.PropertyMapLoader" level="OFF" />
    <logger name="com.avaje.ebeaninternal.server.core.XmlConfigLoader" level="OFF" />
    <logger name="com.avaje.ebeaninternal.server.lib.BackgroundThread" level="OFF" />
    <logger name="com.gargoylesoftware.htmlunit.javascript" level="OFF" />

    <root level="ERROR">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="FILE_ERROR" />
        <appender-ref ref="FILE_WARN" />
        <appender-ref ref="FILE_INFO" />
        <appender-ref ref="FILE_DEBUG" />
    </root>

</configuration>

```

## 動かしてみる

```scala:実行
Logger.debug("debug")
Logger.info("info")
Logger.warn("warn")
Logger.error("error")
```

```bash:ファイルへの出力内容
tail -n 1 logs/{debug,info,warn,error}.log
==> logs/debug.log <==
2015-01-17T15:48:23+0000 [DEBUG] application debug

==> logs/info.log <==
2015-01-17T15:48:23+0000 [INFO] application info

==> logs/warn.log <==
2015-01-17T15:48:23+0000 [WARN] application warn

==> logs/error.log <==
2015-01-17T15:48:23+0000 [ERROR] application error
```

## おわり
EvaluatorFilterを使って、書込内容ごとにログ出力先を分けることも可能ですが、それはまた別ライブラリー紹介と一緒に投稿したいと思います。