Logback とは
Java のロギングライブラリ。
Log4j の開発者が作った別のロギングライブラリ。
歴史的な背景とか、 SLF4J との関係については、 Javaのログ出力: 道具と考え方 というスライドがとても参考になります。
Hello World
インストール
compile 'ch.qos.logback:logback-classic:1.1.3'
実装
package sample.logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(Main.class);
logger.info("Hello Logback!!");
}
}
11:14:22.582 [main] INFO sample.logback.Main - Hello Logback!!
説明
- 依存関係には、とりあえず
logback-classic
を追加すれば動かせる。- 推移的な依存関係の解決で、
logback-core
やslf4j-api
などが付いてくる。
- 推移的な依存関係の解決で、
- Logback を使う場合、 API はログファサードである SLF4J を使用する。
- 設定ファイル(
logback.xml
)が存在しない場合、デフォルトでコンソールにログが出力される。 - ロガーの取得には、
LoggerFactory#getLogger()
を使う。- 引数にはロガーを特定するための名前を渡す。
- 普通は、ロガーを使うクラスの
Class
オブジェクトを渡す。 - すると、クラスの FQCN を名前にしたロガーを取得できる。
Logger
インターフェースの使い方
ログレベル
package sample.logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.Level;
public class Main {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(Main.class);
ch.qos.logback.classic.Logger log = (ch.qos.logback.classic.Logger)logger;
log.setLevel(Level.TRACE); // ★デフォルトだと trace レベルは出力されないので、出力のレベルを TRACE にしている
logger.trace("trace message");
logger.debug("debug message");
logger.info("info message");
logger.warn("warn message");
logger.error("error message");
}
}
11:16:15.220 [main] TRACE sample.logback.Main - trace message
11:16:15.222 [main] DEBUG sample.logback.Main - debug message
11:16:15.222 [main] INFO sample.logback.Main - info message
11:16:15.222 [main] WARN sample.logback.Main - warn message
11:16:15.222 [main] ERROR sample.logback.Main - error message
-
trace
,debug
,info
,warn
,error
の5つのログレベルがある。
パラメータ
package sample.logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(Main.class);
logger.info("{}", "HOGE");
logger.info("{} {}", "HOGE", "FUGA");
logger.info("{} {}", "HOGE");
logger.info("{}", "HOGE", "FUGA");
logger.info("\\{}", "HOGE");
logger.info("{ }", "HOGE");
}
}
11:16:36.758 [main] INFO sample.logback.Main - HOGE
11:16:36.762 [main] INFO sample.logback.Main - HOGE FUGA
11:16:36.762 [main] INFO sample.logback.Main - HOGE {}
11:16:36.762 [main] INFO sample.logback.Main - HOGE
11:16:36.762 [main] INFO sample.logback.Main - {}
11:16:36.762 [main] INFO sample.logback.Main - { }
- 第一引数にパラメータ
{}
を宣言した文字列を渡し、第二引数以降にパラメータに埋め込む値を渡す。 - すると、
{}
の部分に、第二引数以降の値が順番に埋め込まれる。 - パラメータの数と引数の数が一致しない場合は、数が少ない方に合わせられる(エラーにはならない)。
- パラメータの方が多い場合は、そのまま
{}
と出力される(空文字にはならない)。
- パラメータの方が多い場合は、そのまま
- バックスラッシュでエスケープできる。
-
{
と}
の間に文字が入ると埋め込み対象にならなくなる。
スタックトレースの出力
package sample.logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(Main.class);
try {
throw new Exception("test exception");
} catch (Exception e) {
logger.info("error", e);
}
}
}
11:16:57.064 [main] INFO sample.logback.Main - error
java.lang.Exception: test exception
at sample.logback.Main.main(Main.java:12) ~[bin/:na]
- 第一引数に文字列、第二引数に例外を渡すと、スタックトレースをログに出力できる。
設定ファイル
コンソールに出力するアペンダーを定義する
src/main/
|-java/
| `-sample/logback/
| `-Main.java
`-resources/
`-logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<root>
<appender-ref ref="STDOUT" />
</root>
</configuration>
package sample.logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(Main.class);
logger.info("Hello Logback!!");
}
}
Hello Logback!!
- 設定ファイルは、
logback.xml
という名前で作成して、クラスパス直下に配置する。 -
<root>
タグで、ルートロガーの設定を記述する。-
<appender-ref>
でアペンダー(ログの出力先)を指定する。
-
-
<appender>
タグで、アペンダーを定義する。-
<encoder>
タグの<pattern>
タグで、出力のフォーマットを定義する。 -
ch.qos.logback.core.ConsoleAppender
クラスを指定することで、コンソールに出力するアペンダーを定義できる。
-
メッセージのパターンを指定する
変換指定子
メッセージのパターン定義には、 %m
のように %
で始まる特別なパラメータを定義することができる。
パラメータは、次のような書式になっている。
%<変換指定子>{オプション}
変換指定子には、 logger
や msg
など、出力する内容ごとに決められた値を設定する。
オプションには、変換識別子ごとに固有の設定値を渡す。例えば、日付を出力する date
には %date{yyyyMMdd}
のようにフォーマットを渡すことができる。
オプションなので、必要でなければ省略できる。
以下に、よく使いそうな変換指定子の使い方をまとめる。
詳細な使い方や、その他の変換指定子については、PatternLayout | 第6章レイアウトを参照のこと。
実装
package sample.logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(Main.class);
logger.info("Hello Logback!!");
}
}
変換指定子 | 設定例 | 実行結果 | 説明 |
---|---|---|---|
c , lo , logger
|
%c |
sample.logback.Main |
ロガーの名前を出力する。 |
d , date
|
%d |
2015-10-24 00:36:55,947 |
日時を出力する。 |
%d{HH:mm} |
00:57 |
オプションでフォーマットを指定できる。 | |
m , msg , message
|
%m |
Hello Logback!! |
ロガーに渡したメッセージを出力する。 |
n |
a%n b |
a<改行> b |
実行環境に合わせた改行コードを出力する。 |
p , le , level
|
%p |
INFO |
ログレベルを出力する。 |
t , thread
|
%t |
main |
ログ出力時のスレッド名を出力する。 |
変換指定子の直後に文字列を出力する
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>hoge%nfuga</pattern>
</encoder>
</appender>
...
</configuration>
改行を表す %n
の直後に fuga
と出力しようとしている。
しかし、このまま動かすと、 Logback は nfuga
という変換指定子が指定されたものと勘違いして、「そんな変換指定子はない!」とエラーになる。
これを回避するには、空のオプションを指定してあげる。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>hoge%n{}fuga</pattern>
</encoder>
</appender>
...
</configuration>
hoge
fuga
書式修飾子
%
と変換指定子の間に、パディングなどの書式修飾子を指定できる。
書式修飾子のフォーマット
%[書式修飾子]<変換指定子>
書式修飾子:
[最小幅][.最大幅]
最小幅, 最大幅:
整数
設定例 | 出力文字列 | 実行結果 | 説明 |
---|---|---|---|
[%5m] |
"123" |
[ 123] |
最小幅を指定した場合、右寄せして半角スペースでパディング。 |
"123456" |
[123456] |
桁数を越える場合は、省略されずに出力される。 | |
[%.5m] |
"123" |
[123] |
最大幅を指定した場合、桁数を超えた分が左から順に省略される。 |
"123456" |
[23456] |
||
[%-5] |
"123" |
[123 ] |
最小幅をマイナスにすると、左寄せになる。 |
[%.-5] |
"123456" |
[12345] |
最大幅をマイナスにすると、桁数を超えた分が右から順に省略される。 |
[%3.5m] |
"12" |
[ 12] |
最小幅と最大幅を同時に指定することもできる。 |
"1234" |
[1234] |
||
"123456" |
[23456] |
||
[%-3.-5m] |
"12" |
[12 ] |
それぞれマイナスにすることもできる。 |
"1234" |
[1234] |
||
"123456" |
[12345] |
グループを作成する
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%-7([%level]) : %m%n</pattern>
</encoder>
</appender>
<root>
<appender-ref ref="STDOUT" />
</root>
</configuration>
package sample.logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(Main.class);
logger.debug("debug");
logger.info("info");
logger.warn("warn");
logger.error("error");
}
}
[DEBUG] : debug
[INFO] : info
[WARN] : warn
[ERROR] : error
-
()
で括ると、その部分をグループ化させられる。 - グループには書式修飾子を指定できる。
-
(
,)
を普通の文字として使いたい場合は、バックスラッシュ\
でエスケープする。
変数を定義する
基本
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<!-- ★ property タグで宣言 -->
<property name="hoge" value="HOGE" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>hoge = ${hoge}%n</pattern>
</encoder>
</appender>
<root>
<appender-ref ref="STDOUT" />
</root>
</configuration>
package sample.logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(Main.class);
logger.info("");
}
}
hoge = HOGE
-
<propety>
タグを使うことで、変数を定義できる。 -
${<変数名>}
で、変数を参照できる。
システムプロパティの値を参照する
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>hoge = ${hoge}%n</pattern>
</encoder>
</appender>
<root>
<appender-ref ref="STDOUT" />
</root>
</configuration>
package sample.logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(String[] args) {
System.setProperty("hoge", "Hoge"); // ★システムプロパティを設定
Logger logger = LoggerFactory.getLogger(Main.class);
logger.info("");
}
}
hoge = Hoge
-
${<システムプロパティ名>}
で、システムプロパティの値を参照できる。
OS の環境変数を参照する
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<property file="./fuga.properties" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>OS = ${OS}%n</pattern>
</encoder>
</appender>
<root>
<appender-ref ref="STDOUT" />
</root>
</configuration>
OS = Windows_NT
-
${<環境変数名>}
で OS の環境変数を参照できる。 -
<property>
で宣言された変数 → システムプロパティ → 環境変数の順に検索され、最初に見つかった値が採用される。
変数を別ファイルに定義する
fuga=FUGA
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<property file="./fuga.properties" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>fuga = ${fuga}%n</pattern>
</encoder>
</appender>
<root>
<appender-ref ref="STDOUT" />
</root>
</configuration>
fuga = FUGA
-
<property>
タグのfile
属性を指定すれば、別途作成したプロパティファイルを読み込める。 -
file
属性の代わりにresource
属性を指定すれば、クラスパス上のファイルを指定することもできる。
変数のデフォルト値を指定する
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>hoge = ${hoge:-default value}%n</pattern>
</encoder>
</appender>
<root>
<appender-ref ref="STDOUT" />
</root>
</configuration>
hoge = default value
-
${<変数名>:-<デフォルト値>}
という形式で、変数が定義されていなかった場合のデフォルト値を指定できる。
変数名のネスト
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<property name="nest" value="hoge" />
<property name="value.hoge" value="HOGE" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>value.${nest} = ${value.${nest}}%n</pattern>
</encoder>
</appender>
<root>
<appender-ref ref="STDOUT" />
</root>
</configuration>
value.hoge = HOGE
-
${}
は入れ子にできる。 -
${value.${nest}}
が${value.hoge}
になってHOGE
になってる。
設定ファイルを分割する
src/main/
|-java/
| `-Main.java
`resources/
|-logback.xml
`-hoge.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<include resource="hoge.xml" />
<root>
<appender-ref ref="STDOUT" />
</root>
</configuration>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<included>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>hoge : %m%n</pattern>
</encoder>
</appender>
</included>
package sample.logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(Main.class);
logger.info("hello world");
}
}
hoge : hello world
-
<include>
タグを使うと、分割した他の設定ファイルを読み込むことができる。- クラスパス外のファイルを指定する場合は
file
属性でパスを指定する。 - クラスパス上のファイルを指定する場合は
resource
属性で指定する。
- クラスパス外のファイルを指定する場合は
- 読み込まれる側のファイルは、
<included>
タグで囲んだ場所に設定を記述する。
ロガー
ロガーの設定を宣言する
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<logger name="sampleLogger" />
<root>
<appender-ref ref="STDOUT" />
</root>
</configuration>
package sample.logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger("sampleLogger");
logger.debug("hello sampleLogger");
}
}
hello sampleLogger
-
<logger>
タグを使ってsampleLogger
というロガーの設定を宣言している。 -
getLogger()
メソッドの引数でロガーの名前を渡すことで、指定したロガーを取得できる。
ロガーの出力レベルを指定する
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<!-- ★level 属性を指定 -->
<logger name="sampleLogger" level="info" />
<root>
<appender-ref ref="STDOUT" />
</root>
</configuration>
package sample.logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger("sampleLogger");
logger.debug("debug");
logger.info("info");
}
}
info
-
<logger>
タグのlevel
属性で、そのロガーのレベルを指定できる。 - 指定したレベル以上のログだけが出力されるようになる。
ロガーの親子関係
全てのロガーは、ルートロガーを最上位とした親子関係になっている。
ロガーの名前にドット (.
) が含まれる場合、 .
が親子関係の区切りを表すことになる。
例えば、 foo.bar.Hoge
という名前のロガーは、 foo.bar
というロガーの子供ということになる。
また、 foo.bar
ロガーは、 foo
というロガーの子供になる。
そして、 foo
ロガーはルートロガーの子供になる。
子供のロガーは、親のロガーに設定されているレベルやアペンダーを継承するようになっている。
つまり、子供のロガーで設定を記述しない場合は、デフォルトで親のロガーと同じ設定が適用されることになる。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<logger name="foo" level="trace" />
<logger name="foo.bar" level="info" />
<root>
<appender-ref ref="STDOUT" />
</root>
</configuration>
package sample.logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(String[] args) {
log("foo");
log("foo.Fuga");
log("foo.bar");
log("foo.bar.Hoge");
}
private static void log(String loggerName) {
Logger logger = LoggerFactory.getLogger(loggerName);
System.out.println("[" + loggerName + "]");
logger.trace("trace");
logger.debug("debug");
logger.info("info");
System.out.println();
}
}
[foo]
trace
debug
info
[foo.Fuga]
trace
debug
info
[foo.bar]
info
[foo.bar.Hoge]
info
- ルートロガーは、デフォルトでレベルが
debug
になっている。 - それを、
foo
ロガーでtrace
に上書きしている。 - さらに、その設定を
foo.bar
ロガーではinfo
に上書きしている。 -
foo
ロガーの子供であるfoo.Fuga
ロガーは、foo
ロガーの設定を継承してtrace
レベルまでログが出力されている。 - 一方で、
foo.bar.Hoge
ロガーはfoo.bar
ロガーの設定を継承してinfo
レベルのログしか出力されていない。
ロガーの名前
一般的に、ロガーの名前にはそのロガーを使用するクラスの FQCN を使用するのが良いとされている。
そうすることで、パッケージ名がそのロガーの親ロガーということになり、パッケージ単位でロガーの設定を変更する、といった調整が可能になる。
ロガーの名前を FQCN にする場合、文字列で指定するのではなく Class
オブジェクトを渡す方が良い。
そうしておけば、クラス名の変更やパッケージの移動が必要になったときでも IDE のリファクタリング機能を使うことで自動でロガー名を変更できるようになる。
ただし、クラス名にしなければならない、というわけではなく、用途に合わせた名称でロガーを宣言しても問題はない。
アペンダーを設定する
アペンダーとは、実際にログを出力するコンポーネントで、ログの出力先(コンソール、ファイル、データベース)やフォーマットなどを指定することができる。
ロガーにアペンダーを設定することで、そのロガーを使ったときのログ出力方法が決定される。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="STDOUT1" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>STDOUT1 : %msg%n</pattern>
</encoder>
</appender>
<appender name="STDOUT2" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>STDOUT2 : %msg%n</pattern>
</encoder>
</appender>
<logger name="foo.bar.Hoge">
<appender-ref ref="STDOUT2" />
</logger>
<root>
<appender-ref ref="STDOUT1" />
</root>
</configuration>
package sample.logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger("foo.bar.Hoge");
logger.info("hello appender");
}
}
STDOUT2 : hello appender
STDOUT1 : hello appender
-
<appender>
タグを使って、アペンダーを定義できる。 -
<appender>
タグには、name
とclass
という必須の属性が2つある。-
name
は、そのアペンダーの名前を任意に指定する。 -
class
は、アペンダーの具体的な実装クラスを FQCN で指定する。-
ch.qos.logback.core.ConsoleAppender
は Logback が提供しているアペンダーで、コンソールにログを出力するアペンダーになる。
-
-
- ロガーにアペンダーを設定するには、子供要素に
<appender-ref>
タグを追加する。-
ref
属性に、設定するアペンダーのname
を指定する。
-
アペンダーの設定は積み重ねられる
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<logger name="foo.bar.Hoge">
<appender-ref ref="STDOUT" />
</logger>
<root>
<appender-ref ref="STDOUT" />
</root>
</configuration>
ルートロガーと foo.bar.Hoge
ロガーに、それぞれ STDOUT
アペンダーを設定している。
この場合、アペンダーの名前が一緒だからルートロガーの STDOUT
は foo.bar.Hoge
の STDOUT
で上書きされて結果的に1つのアペンダーが設定されるのかという、そうではない。
package sample.logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger("foo.bar.Hoge");
logger.info("hello appender");
}
}
hello appender
hello appender
アペンダーの設定は積み重ねられるので、 foo.bar.Hoge
ロガーはルートロガーで設定された STDOUT
と自身に設定された STDOUT
に2回ログ出力を指示することになる。
結果、ログは重複して出力される。
アペンダーの積み重ねを止める
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="STDOUT1" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>STDOUT1 : %msg%n</pattern>
</encoder>
</appender>
<appender name="STDOUT2" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>STDOUT2 : %msg%n</pattern>
</encoder>
</appender>
<appender name="STDOUT3" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>STDOUT3 : %msg%n</pattern>
</encoder>
</appender>
<!-- ★ additivity に false を設定 -->
<logger name="foo.bar" additivity="false">
<appender-ref ref="STDOUT2" />
</logger>
<logger name="foo.bar.Hoge">
<appender-ref ref="STDOUT3" />
</logger>
<root>
<appender-ref ref="STDOUT1" />
</root>
</configuration>
package sample.logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(String[] args) {
log("foo.bar");
log("foo.bar.Hoge");
}
private static void log(String loggerName) {
Logger logger = LoggerFactory.getLogger(loggerName);
System.out.println("[" + loggerName + "]");
logger.info("hello appender");
System.out.println();
}
}
[foo.bar]
STDOUT2 : hello appender
[foo.bar.Hoge]
STDOUT3 : hello appender
STDOUT2 : hello appender
-
<logger>
タグのadditivity
属性にfalse
を設定すると、親のロガーに設定されていたアペンダーを継承しなくなる。 -
additivity="false"
を設定したロガーの子供は、再び親のアペンダーを継承するようになる。
ファイル出力
基本
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>logback-sample.log</file>
<encoder>
<charset>UTF-8</charset>
<pattern>%m%n</pattern>
</encoder>
</appender>
<root>
<appender-ref ref="FILE" />
</root>
</configuration>
package sample.logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(Main.class);
logger.info("hello world");
}
}
hello world
-
ch.qos.logback.core.FileAppender
でアペンダーを定義すると、ファイル出力が可能になる。 -
<file>
タグで出力ファイルを指定する。 - ファイルがなければ作成する。
- ファイルまでのフォルダがなければ、勝手に作成してくれる。
- 文字コードは
<encoder>
タグの下に<charset>
タグを入れて設定する。
ファイル名にタイムスタンプを入れる
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<timestamp key="time" datePattern="yyyyMMdd_HHmmss" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>logback-sample_${time}.log</file>
<encoder>
<pattern>%m%n</pattern>
</encoder>
</appender>
<root>
<appender-ref ref="FILE" />
</root>
</configuration>
|-logback-sample_20151024_230826.log
`-src/
hello world
-
<timestamp>
タグで実行日時を記録した変数を定義できる。 -
key
属性に他から参照のための名前を。 -
datePattern
属性に日付書式を指定する。
ローテーションさせる
ログファイルをローテーションさせる場合は、アペンダーのクラスに ch.qos.logback.core.rolling.RollingFileAppender
を指定する。
時間基準でローテーションさせる
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logback-sample.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logback-sample-%d{yyyyMMdd_HHmmss}.log</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>%m%n</pattern>
</encoder>
</appender>
<root>
<appender-ref ref="FILE" />
</root>
</configuration>
何度かログ出力を実行する。
|-logback-sample.log
|-logback-sample-20151024_232440.log
|-logback-sample-20151024_232459.log
|-logback-sample-20151024_232501.log
`-src/
-
<rollingPolicy>
タグにch.qos.logback.core.rolling.TimeBasedRollingPolicy
を指定する。 -
<fileNamePattern>
タグで、ローテーション後のファイル名を指定する。 - 日付部分の書式には、
%d
を使用する。- 具体的なフォーマットの指定は
%d{yyyyMMdd}
のように、変換指定子の場合と同じ要領で記述する。 - オプションを指定しない場合、デフォルトで
yyyy-MM-dd
という日付書式が使用される。
- 具体的なフォーマットの指定は
- ローテーションは、日付の書式から自動的に推測されて実行される。
-
%d{yyyyMMdd_HHmmss}
の場合は秒まで書式が指定されているので、秒が切り替わればローテーションが実行される。 -
%d{yyyy-MM-dd}
なら日付が切り替わればローテーションされる。
-
古いログファイルを自動で削除する
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logback-sample.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logback-sample-%d{yyyyMMdd_HH}.log</fileNamePattern>
<maxHistory>3</maxHistory> <!-- ★最大保持件数を設定 -->
</rollingPolicy>
<encoder>
<pattern>%m%n</pattern>
</encoder>
</appender>
<root>
<appender-ref ref="FILE" />
</root>
</configuration>
2015/10/24 18:00 52 logback-sample-20151024_18.log
2015/10/24 19:00 52 logback-sample-20151024_19.log
2015/10/24 20:00 52 logback-sample-20151024_20.log
2015/10/24 21:00 52 logback-sample-20151024_21.log
2015/10/24 22:00 37 logback-sample.log
2015/10/24 20:00 52 logback-sample-20151024_20.log
2015/10/24 21:00 52 logback-sample-20151024_21.log
2015/10/24 22:00 37 logback-sample-20151024_22.log
2015/10/24 23:58 37 logback-sample.log
-
<maxHistory>
タグで、いくつ前までのログファイルを保持するかを設定できる。 - 日付書式が
%d{yyyyMMdd_HH}
で、maxHistory
が3
なので、「3時間より前のファイル」は削除されることになる。- ログ出力が23時なので、それより3時間前(20時)より前(19時以前)のファイルは全て削除される。
毎日ローテーションさせつつ過去ログは月ごとのフォルダに格納する
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logback-sample.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>%d{yyyyMM,aux}/logback-sample-%d{yyyyMMdd}.log</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>%m%n</pattern>
</encoder>
</appender>
<root>
<appender-ref ref="FILE" />
</root>
</configuration>
- 月ごとのフォルダを表す部分に
%d{yyyyMM,aux}
というふうにaux
オプションを指定する。-
aux
はauxiliary
(補助)の略で、これが設定された%d
はファイルローテーションのタイミングとしては識別されなくなる。 - この場合、
aux
が指定されていない%d{yyyyMMdd}
の方がファイルローテーションのタイミングとして認識される。
-
過去ログを圧縮する
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logback-sample.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logback-sample_%d{yyyyMMdd_HHmmss}.zip</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>%m%n</pattern>
</encoder>
</appender>
<root>
<appender-ref ref="FILE" />
</root>
</configuration>
-
<fileNamePattern>
に指定するファイル名の拡張子をzip
やgz
にすれば、自動的に圧縮してくれる。
メールで送信する
SMTPAppender
を使うと、 error
レベルのログを出力したタイミングでメールを送信することができる。
試しに GMail を使ってメールを送信する。
dependencies {
compile 'ch.qos.logback:logback-classic:1.1.3'
compile 'javax.mail:mail:1.4.7' // ★ Java Mail を追加
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
<smtpHost>smtp.gmail.com</smtpHost>
<smtpPort>465</smtpPort>
<SSL>true</SSL>
<username>xxxxxxxxxxxxxxxx@gmail.com</username>
<password>xxxxxxxxxxxxxxxxxxxxx</password>
<to>yyyyyyyyyyyy@gmail.com</to>
<from>xxxxxxxxxxxxxxxx@gmail.com</from>
<subject>Logback SMTPAppender Sample</subject>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%m%n</pattern>
</layout>
</appender>
<root>
<appender-ref ref="EMAIL" />
</root>
</configuration>
package sample.logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(String[] args) throws Exception {
Logger logger = LoggerFactory.getLogger(Main.class);
for (int i=0; i<256; i++) {
logger.info("i=" + i);
}
logger.error("error!!");
// ★メールの送信が完了するまで少し待機
Thread.sleep(5000);
}
}
実行結果
- メール送信を使うには
ch.qos.logback.classic.net.SMTPAppender
をアペンダーとして指定する。 - 各設定は以下のような感じ。
設定 | 説明 |
---|---|
<smtpHost> |
SMTP サーバーのホスト名 |
<smtpPort> |
SMTP サーバーのポート番号。デフォルトは 25 。 |
<SSL> |
true を指定すると、 SMTP サーバーに SSL で接続する。 |
<username> |
SMTP サーバーの接続に認証が必要な場合のユーザー名。 |
<password> |
同接続用のパスワード。 |
<to> |
送信先のメールアドレス。<to> を複数宣言するか、カンマ , 区切りで複数の宛先を指定可能。 |
<from> |
送信元のメールアドレス。 |
<subject> |
メールの件名。 %logger などの変換指定子も指定可能。 |
-
SMTPAppender
に出力されたログは、デフォルトで最大 256 個までキャッシュされる。 -
error
レベルでログを出力すると、このキャッシュされたログとerror
レベルで出力したログの内容がメールで送信される。 - メールの送信処理は、デフォルトでは非同期で行われる。
- サンプルでは
Thread.sleep()
を入れてメールの送信が完了するのを待機している。 - こうしないと、非同期で行われているメールの送信が完了する前に JVM が終了してしまい、動作の確認ができなかった。
- サンプルでは
Gmail で送信するときのパスワードについて
二段階認証を有効にしている場合、アプリパスワードを発行する必要がある。
キャッシュするログの量を変更する
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
<smtpHost>smtp.gmail.com</smtpHost>
<smtpPort>465</smtpPort>
<SSL>true</SSL>
<username>xxxxxxxxxxxxxxxx@gmail.com</username>
<password>xxxxxxxxxxxxxxxxxxxxx</password>
<to>yyyyyyyyyyyy@gmail.com</to>
<from>xxxxxxxxxxxxxxxx@gmail.com</from>
<subject>Logback SMTPAppender Sample</subject>
<!-- ★キャッシュサイズを変更 -->
<cyclicBufferTracker class="ch.qos.logback.core.spi.CyclicBufferTracker">
<bufferSize>10</bufferSize>
</cyclicBufferTracker>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%m%n</pattern>
</layout>
</appender>
<root>
<appender-ref ref="EMAIL" />
</root>
</configuration>
実行結果
-
<cyclicBufferTracker class="ch.qos.logback.core.spi.CyclicBufferTracker">
を追加して、<bufferSize>
タグでキャッシュするログの量を指定できる。
メールの送信を同期処理にする
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
<smtpHost>smtp.gmail.com</smtpHost>
<smtpPort>465</smtpPort>
<SSL>true</SSL>
<username>xxxxxxxxxxxxxxxx@gmail.com</username>
<password>xxxxxxxxxxxxxxxxxxxxx</password>
<to>yyyyyyyyyyyy@gmail.com</to>
<from>xxxxxxxxxxxxxxxx@gmail.com</from>
<subject>Logback SMTPAppender Sample</subject>
<!-- ★同期処理 -->
<asynchronousSending>false</asynchronousSending>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%m%n</pattern>
</layout>
</appender>
<root>
<appender-ref ref="EMAIL" />
</root>
</configuration>
-
<asynchronousSending>
タグを追加してfalse
を指定すると、メールの送信が同期処理になる。 - エラーが発生すると、その直後に JVM を終了させてしまうようなアプリの場合は、メールの送信を同期にしておく必要がある。
フィルター
アペンダーにフィルターを設定することで、特定の条件に一致したログだけを出力できるようになる。
特定のログレベルだけを出力させる(させない)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="DENY_INFO" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>DENY</onMatch>
</filter>
<encoder>
<pattern>%level %n</pattern>
</encoder>
</appender>
<appender name="ACCEPT_DEBUG" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder>
<pattern>%level %n</pattern>
</encoder>
</appender>
<logger name="accept.debug">
<appender-ref ref="ACCEPT_DEBUG" />
</logger>
<logger name="deny.info">
<appender-ref ref="DENY_INFO" />
</logger>
<root level="trace">
</root>
</configuration>
package sample.logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(String[] args) throws Exception {
log("accept.debug");
log("deny.info");
}
private static void log(String loggerName) {
Logger logger = LoggerFactory.getLogger(loggerName);
System.out.println("[" + loggerName + "]");
logger.trace("");
logger.debug("");
logger.info("");
logger.warn("");
logger.error("");
System.out.println();
}
}
[accept.debug]
DEBUG
[deny.info]
TRACE
DEBUG
WARN
ERROR
-
<filter>
タグを追加し、class
にch.qos.logback.classic.filter.LevelFilter
を設定する。 -
<level>
タグに、対象のログレベルを指定する。 -
<onMatch>
および<onMismatch>
タグに、ログレベルがマッチした場合にどうするかを指定する。-
DENY
を指定すると、出力は完全に中断される(他のフィルタの処理はスキップされる)。 -
ACCEPT
を指定すると、出力が許可される(他のフィルタの処理はスキップされる)。 -
NEUTRAL
を指定すると、現在のフィルタはスキップされ次のフィルタに処理が送られる。
-
あるログレベルより低いログレベルを出力させないようにする
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>WARN</level>
</filter>
<encoder>
<pattern>%level %n</pattern>
</encoder>
</appender>
<root level="trace">
<appender-ref ref="CONSOLE" />
</root>
</configuration>
package sample.logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(String[] args) throws Exception {
Logger logger = LoggerFactory.getLogger(Main.class);
logger.trace("");
logger.debug("");
logger.info("");
logger.warn("");
logger.error("");
}
}
WARN
ERROR
-
ch.qos.logback.classic.filter.ThresholdFilter
をフィルターに指定することで、<level>
で指定したログより低いレベルのログ出力を抑制できる。
特定の文字列が含まれるログだけを出力する
dependencies {
compile 'ch.qos.logback:logback-classic:1.1.3'
compile 'janino:janino:2.5.10' // ★追加
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator>
<matcher>
<name>hogeMatcher</name>
<regex>hoge</regex>
</matcher>
<expression>hogeMatcher.matches(formattedMessage)</expression>
</evaluator>
<OnMismatch>DENY</OnMismatch>
</filter>
<encoder>
<pattern>%m%n</pattern>
</encoder>
</appender>
<root>
<appender-ref ref="CONSOLE" />
</root>
</configuration>
package sample.logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(String[] args) throws Exception {
Logger logger = LoggerFactory.getLogger(Main.class);
logger.info("hoge");
logger.info("fuga");
logger.info("piyo");
logger.info("hoge fuga");
logger.info("hoge piyo");
}
}
hoge
hoge fuga
hoge piyo
- 依存関係に
janino:janino:2.5.10
を追加する。 -
<filter>
にch.qos.logback.core.filter.EvaluatorFilter
を設定する。 -
<evaluator>
タグを追加し、<matcher>
タグで文字列を検証するためのMatcher
を定義する。-
<name>
属性でそのMatcher
の名前を、<regex>
タグでマッチの条件となる正規表現を定義する。 -
<expression>
タグで、Matcher
を使った値の検証ロジックを記述する。-
Matcher
を使わなくても、評価結果がboolean
になるのであれば、任意の Java コードを記述することができる。
-
-
formattedMessage
は<expression>
タグ中で参照可能な暗黙の変数で、最終的に出力されようとしている文字列が格納されている。
-
-
hoge
という文字列が含まれているメッセージのみがログ出力されている。
<expression>
タグ中で参照できる暗黙の変数(一部)
変数名 | 型 | 説明 |
---|---|---|
message |
String |
ロガーに渡されたメッセージ。パラメータ({} )もそのままの形で渡される。 |
formattedMessage |
String |
最終的に出力されようとしている文字列。 |
logger |
String |
ロガーの名前。 |
level |
int |
ログレベルを表す整数値。 |
DEBUG |
int |
debug のログレベルを表す整数値。 |
INFO |
int |
info のログレベルを表す整数値。 |
WARN |
int |
warn のログレベルを表す整数値。 |
ERROR |
int |
error のログレベルを表す整数値。 |
marker |
Marker |
ログ出力のときに指定されたマーカーオブジェクト。 |
throwable |
Throwable |
ログ出力のときに渡された例外オブジェクト。 |
より詳細な情報は JaninoEventEvaluator | 第7章フィルター を参照のこと。
フィルターを自作する
package sample.logback;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.filter.Filter;
import ch.qos.logback.core.spi.FilterReply;
public class MyFilter extends Filter<ILoggingEvent> {
private String value;
@Override
public FilterReply decide(ILoggingEvent event) {
if (event.getMessage().contains(this.value)) {
return FilterReply.ACCEPT;
} else {
return FilterReply.DENY;
}
}
public void setValue(String value) {
this.value = value;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="sample.logback.MyFilter">
<value>hoge</value>
</filter>
<encoder>
<pattern>%m%n</pattern>
</encoder>
</appender>
<root>
<appender-ref ref="CONSOLE" />
</root>
</configuration>
package sample.logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(String[] args) throws Exception {
Logger logger = LoggerFactory.getLogger(Main.class);
logger.info("a hoge");
logger.info("Hoge");
logger.info("hoge b");
logger.info("hoGe");
}
}
a hoge
hoge b
-
Filter
クラスを継承することで、任意のフィルターを自作することができる。 -
decide()
メソッドをオーバーライドして、フィルタリングの定義を実装する。-
FilterReply.ACCEPT
を返せば、後続のフィルターを飛ばして出力を許可する。 -
FilterReply.DENY
を返せば、後続のフィルターを飛ばして出力を拒否する。 -
FilterReply.NEUTRAL
を返せば、後続のフィルターに処理を続けさせる。
-
- setter を定義することで、任意のオプションを
<filter>
タグの子要素として指定できるようになる。
設定例
info 以上のログをコンソールとファイルに出力する
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<property name="format" value="[%-5level] %date %-15logger{15} - %m%n" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>sample.log</file>
<encoder>
<pattern>${format}</pattern>
</encoder>
</appender>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${format}</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</configuration>
ファイル出力は特定のパッケージ以下だけ
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<property name="format" value="[%-5level] %date %-15logger{15} - %m%n" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>sample.log</file>
<encoder>
<pattern>${format}</pattern>
</encoder>
</appender>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${format}</pattern>
</encoder>
</appender>
<logger name="sample">
<appender-ref ref="FILE" />
</logger>
<root level="info">
<appender-ref ref="CONSOLE" />
</root>
</configuration>
ログファイルのローテーションを設定
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<property name="format" value="[%-5level] %date %-15logger{15} - %m%n" />
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>log/sample.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>log/%d{yyyyMM,aux}/sample-%d{yyyyMMdd}.log</fileNamePattern>
<maxHistory>90</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${format}</pattern>
</encoder>
</appender>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${format}</pattern>
</encoder>
</appender>
<logger name="sample">
<appender-ref ref="FILE" />
</logger>
<root level="info">
<appender-ref ref="CONSOLE" />
</root>
</configuration>
-
log
フォルダの下に月ごとのフォルダを作り、その下に過去ログを格納。 - 最大3ヶ月(90日)分のログを保持しておく。
環境変数 LOG_LEVEL
に合わせて出力のログレベルを切り替える
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<property name="format" value="[%-5level] %date %-15logger{15} - %m%n" />
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>log/sample.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>log/%d{yyyyMM,aux}/sample-%d{yyyyMMdd}.log</fileNamePattern>
<maxHistory>90</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${format}</pattern>
</encoder>
</appender>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${format}</pattern>
</encoder>
</appender>
<logger name="sample">
<appender-ref ref="FILE" />
</logger>
<root level="${LOG_LEVEL:-info}">
<appender-ref ref="CONSOLE" />
</root>
</configuration>
- 未指定の場合は
info
レベルで出力。
ERROR レベルの出力があったらメールを送信する
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE logback>
<configuration>
<property name="format" value="[%-5level] %date %-15logger{15} - %m%n" />
<appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
<smtpHost>smtp.gmail.com</smtpHost>
<smtpPort>465</smtpPort>
<SSL>true</SSL>
<username>xxxxx@gmail.com</username>
<password>xxxxx</password>
<to>xxxxx@gmail.com</to>
<from>xxxxx@gmail.com</from>
<subject>[System Error] %date{yyyy-MM-dd HH:mm:ss} - %m</subject>
<asynchronousSending>false</asynchronousSending>
<cyclicBufferTracker class="ch.qos.logback.core.spi.CyclicBufferTracker">
<bufferSize>50</bufferSize>
</cyclicBufferTracker>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>${format}</pattern>
</layout>
</appender>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>log/sample.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>log/%d{yyyyMM,aux}/sample-%d{yyyyMMdd}.log</fileNamePattern>
<maxHistory>90</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${format}</pattern>
</encoder>
</appender>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${format}</pattern>
</encoder>
</appender>
<logger name="sample">
<appender-ref ref="FILE" />
</logger>
<root level="${LOG_LEVEL:-info}">
<appender-ref ref="CONSOLE" />
<appender-ref ref="EMAIL" />
</root>
</configuration>
- メール送信は、念のため同期処理で実行。
eclipse での logback.xml の警告表示を無くす
eclipse でスキーマ定義のない xml ファイルを作ると、黄色く警告アイコンが表示されて鬱陶しい。
これを回避するには、先頭に <!DOCTYPE logback>
と入れてあげるといいらしい。
<?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE logback>
<configuration>
...
</configuration>