SpringBootログ出力まとめ（slf4j + logback）

# slf4jとlogbackの関係
slf4j⇒ロギングのファサード。ログ出力の窓口としての役割を持つ。
logback⇒ロギングライブラリ。ログ出力の実装を持つ。

slf4jとlogbackを組み合わせて使用します。
slf4jはlogbackなどのロギングライブラリのファサードとして機能し、slf4jがlogbackのログ出力処理を呼び出します。

# SpringBootで使うには?
SpringBootではデフォルトでslf4jとlogbackが使われるため、ライブラリの追加などは必要ありません。

# ログ設定ファイル
「logback-spring.xml」または「logback.xml」をsrc/main/resourceに配置すると自動で適用されます。
Spring Boot1.3からは「logback-spring.xml」が推奨されています。　[リリースノート参照](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-1.3-Release-Notes)
設定ファイルの場所を変更したい場合は application.properties に下記のように設定します。

```properties:application.properties
## Logger
## 例）src/main/resource/logbackに設定ファイルを配置
logging.config=classpath:logback/logback-spring.xml
```

# logbackの構成要素

|  種類  |  概要  |
| ---- | ---- |
|  appender  |  ログ出力先やログフォーマットを設定。logger、rootで指定される。  |
|  logger  |  どのログレベルで出力するかを設定。子要素にappenderを指定することで出力先などを設定する。  |
|  root  |  loggerの共通設定。  |

# アペンダー

＜アペンダータグの属性＞

|  属性  |  必須  |  概要  |
| ---- | :---: | ---- |
|  name  | ○ |  Appendarの名前。appendar-refで指定される任意の名前。  |
|  class  | ○ |  Appender実装クラスを指定。  |

＜Appendar実装クラス＞

|  クラス名  |  概要  |
| ---- | ---- |
|  ConsoleAppender |  コンソール出力。  |
|  FileAppender  |  ファイル出力。  |
|  RollingFileAppender  |  ファイル出力。ファイルサイズによってログファイルのローテーションを行う。  |

＜アペンダー設定のサンプル＞

```xml:logback-spring.xml
<!-- コンソール出力 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <target>System.out</target>
    <encoder>
        <charset>UTF-8</charset>
        <pattern>%d{yyyy/MM/dd HH:mm:ss} %-5level [%thread] - %msg%n</pattern>
    </encoder>
</appender>

<!-- アプリケーションログのファイル書き出し -->
<appender name="APPLIATION_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <!--ファイル名設定 -->
    <file>/var/log/production/app.log</file>
    <!--ログファイルのローテーション設定 -->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <fileNamePattern>/var/log/production/app-%d{yyyy-MM-dd}.log.zip</fileNamePattern>
        <maxHistory>3</maxHistory>
    </rollingPolicy>
    <!--ログ出力フォーマット設定 -->
    <encoder>
        <charset>UTF-8</charset>
        <pattern>%d{yyyy/MM/dd HH:mm:ss} %-5level [%thread] - %msg%n</pattern>
    </encoder>
</appender>
```

# ロガー

＜ロガータグの属性＞

|  属性  |  必須  |  概要  |
| ---- | :---: | ---- |
|  name  | ○ |  loggerの名前。パッケージ名の指定も可能。  |
|  level  | ○ |  ログレベルを指定。  |
|  additivity  | ○ |  rootや親パッケージで指定したログの出力を行うかを指定。デフォルトはtrue。  |

＜ログレベル＞
TRACE, DEBUG, INFO, WARN, ERROR の５つのログレベルがあります。大文字小文字は区別されません。
ログレベルの関係は下記。
![ログレベル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1798422/6c8f3f2e-cbca-4671-7603-7c520339c068.png)
設定したログレベルを含めて、それより高いログレベルのログが出力されます。
例）ログレベル「INFO」を設定した場合、出力されるのは「INFO」「WARN」「ERROR」になります。

＜ロガー設定のサンプル＞

```xml:logback-spring.xml
<logger name="appLogger" level="INFO">
  <appender-ref ref="APPLIATION_LOG" />
</logger>
```

# ルート
必須の要素。loggerでログレベルの指定がない場合はルートのログレベルで出力されます。
子要素にアペンダーを指定した場合は全てのロガーに適用されます。
※ロガーでadditivity=falseの場合は適用されない。

＜ルートタグの属性＞

|  属性  |  必須  |  概要  |
| ---- | :---: | ---- |
|  level  |  |  ログレベルを指定。デフォルトはDEBUG。  |

＜ルート設定のサンプル＞

```xml:logback-spring.xml
<root level="INFO">
    <appender-ref ref="STDOUT" />
</root>
```

# ここまでのlogback-spring.xml
```xml:logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
 
    <!-- コンソール出力 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <target>System.out</target>
        <encoder>
            <charset>UTF-8</charset>
            <pattern>%d{yyyy/MM/dd HH:mm:ss} %-5level [%thread] - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- アプリケーションログのファイル書き出し -->
    <appender name="APPLIATION_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--ファイル名設定 -->
        <file>/var/log/production/app.log</file>
        <!--ログファイルのローテーション設定 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>/var/log/production/app-%d{yyyy-MM-dd}.log.zip</fileNamePattern>
            <maxHistory>3</maxHistory>
        </rollingPolicy>
        <!--ログ出力フォーマット設定 -->
        <encoder>
            <charset>UTF-8</charset>
            <pattern>%d{yyyy/MM/dd HH:mm:ss} %-5level [%thread] - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- ロガー -->
    <logger name="appLogger" level="INFO">
      <appender-ref ref="APPLIATION_LOG" />
    </logger>

    <!-- ルート -->
    <root level="INFO">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>
```

# ロガーの使い方

ロガーの使い方①

```java:TestController.java
package com.example.demo.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
	
    /** 特定のロガーの指定がないため、rootが適用される */
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@GetMapping("/test")
	public void test() {
		logger.info("ログテスト");
	}
}
```

ロガーの使い方②

```java:TestController.java
package com.example.demo.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
	
    /** ロガー名「appLogger」を指定していためappLoggerが適用される */
    private final Logger logger = LoggerFactory.getLogger("appLogger");
	
	@GetMapping("/test")
	public void test() {
		logger.info("ログテスト");
	}
}
```

ロガーの使い方③

```xml:logback-spring.xml
    <!-- ロガー -->
    <!-- nameをパッケージに変更--!>
    <!-- 指定したパッケージ配下に適用される(com.example.demo.controller.xxxにも適用される)--!>
    <logger name="com.example.demo.controller" level="INFO">
      <appender-ref ref="APPLIATION_LOG" />
    </logger>
```

```java:TestController.java
package com.example.demo.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
	
    /** name="com.example.demo.controller"のロガーが適用される */
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@GetMapping("/test")
	public void test() {
		logger.info("ログテスト");
	}
}
```

# 環境別の設定
開発時と本番時でログの出力先やログレベルを変えたいなどの場合の設定方法です。
<springProfile>タグを使って環境別の設定を行います。

```xml:logback-spring.xml
<!--開発環境用設定 -->
<springProfile name="dev">
    <property name="logFilePath" value="/var/log/dev/" />
    <property name="logLevel" value="DEBUG" />
</springProfile>
    
<!--uat環境用設定 -->
<springProfile name="uat">
    <property name="logFilePath" value="/var/log/uat/" />
　　<property name="logLevel" value="INFO" />
</springProfile>
 
<!--production環境用設定 -->
<springProfile name="production">
    <property name="logFilePath" value="/var/log/production/" />
　　<property name="logLevel" value="INFO" />
</springProfile>
```

環境の切り替えは application.properties で行います。

```properties:application.properties
# 開発環境の場合
spring.profiles.active=dev
# uat環境の場合
spring.profiles.active=uat
# production環境の場合
spring.profiles.active=production
```

# 最終版 logback-spring.xml

```xml:logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>

    <!--開発環境用設定 -->
    <springProfile name="dev">
        <property name="logFilePath" value="/var/log/dev/" />
        <property name="logLevel" value="DEBUG" />
    </springProfile>

    <!--uat環境用設定 -->
    <springProfile name="uat">
        <property name="logFilePath" value="/var/log/uat/" />
　　    <property name="logLevel" value="INFO" />
    </springProfile>

    <!--production環境用設定 -->
    <springProfile name="production">
        <property name="logFilePath" value="/var/log/production/" />
　　    <property name="logLevel" value="INFO" />
    </springProfile>
 
    <!-- コンソール出力 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <target>System.out</target>
        <encoder>
            <charset>UTF-8</charset>
            <pattern>%d{yyyy/MM/dd HH:mm:ss} %-5level [%thread] - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- アプリケーションログのファイル書き出し -->
    <appender name="APPLIATION_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--ファイル名設定 -->
        <file>${logFilePath}${logFileName}.log</file>
        <!--ログファイルのローテーション設定 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${logFilePath}${logFileName}-%d{yyyy-MM-dd}.log.zip</fileNamePattern>
            <maxHistory>3</maxHistory>
        </rollingPolicy>
        <!--ログ出力フォーマット設定 -->
        <encoder>
            <charset>UTF-8</charset>
            <pattern>%d{yyyy/MM/dd HH:mm:ss} %-5level [%thread] - %msg%n</pattern>
        </encoder>
    </appender>

    <!-- ロガー -->
    <logger name="appLogger" level="INFO">
      <appender-ref ref="APPLIATION_LOG" />
    </logger>

    <!-- ルート -->
    <root level="INFO">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

```