javaのロギングツールslf4j(Simple Logging Facade For Java)、logbackについて。

slf4j(公式)
logback(公式)

そのまえに、javaのロギングについての前知識。参考:javaのろがーが多すぎて訳がわからないので整理してみました。

とりあえず、mavenなしで設定。実行環境はeclipseでただのjavaプロジェクト。公式からzipを落として来たら、たくさんjarが入ってる。とりあえずログを出力するだけなら、slf4jからslf4j-api-1.7.5.jar、logbackからlogback-access-1.0.13.jar、logback-classic-1.0.13.jar、logback-core-1.0.13.jarが必要になる。これで下のコードみたいに書けば、標準出力にログがでる。

private static final Logger logger = LoggerFactory.getLogger(TestEntry.class);
logger.info("infoです。");

どのjarが必要か?はここの図 が参考になると思う。

ログレベルは、緩い方からTRACE,DEBUG,INFO,WARN,ERROR。

ログの設定ファイルlogback.xmlを使い時は、デフォルトだとsrc直下に置いとけば自動で読み込んでくれる。このあたりや書式は下が参考になる。
logback.xmlを設定して、運用する
Logbackの構成 - logback.xml

ログをファイル出力したい場合、logback.xmlをこんな感じで。

<configuration>

<appender name="FILE2" class="ch.qos.logback.core.FileAppender">
<File>testLogfile.log</File>
<Append>true</Append>
<Encoding>UTF-8</Encoding>
<BufferedIO>false</BufferedIO>
<ImmediateFlush>true</ImmediateFlush>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy.MM.dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</layout>
</appender>

<root level="INFO">
<appender-ref ref="FILE2" />
<appender-ref ref="STDOUT" />
</root>

</configuration>

これだと、srcディレクトリ直下にtestLogile.logが出力される。出力するログファイルのフルパスも指定できる。
<File>/var/testLogfile.log</File>

(*注)rootタグをappenderタグより先に書いたら、ログを出力できなかった。

■読み込むlogback.xmlのパスを指定したい場合(設定ファイルを外だしして、jarやwarに変更を加えたくない時とか)

main文の最初にこんな感じで。

LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
JoranConfigurator configurator = new JoranConfigurator();
configurator.setContext(lc);
lc.reset();
try {
configurator.doConfigure("/var/logback.xml");
} catch (JoranException e1) {
// TODO 自動生成された catch ブロック
e1.printStackTrace();
}

参考:slf4j+logbackを使ってみる

・例外のprintstacktraceをログ出力したい時はこんな感じ。log4jと一緒。slf4jがIFだから当たり前か。
logger.error("", e);

■ログフォーマット
・ログに時間、クラス名、メッセージを出力。プレースホルダもできる。例えば、したみたいな感じ。
<pattern>%d{yyyy.MM.dd HH:mm:ss} [%thread] %-5level %logger{36} [%method] - %msg%n</pattern>

・参考:logbackwiki。パターン定数、プレースホルダ。

■プレースホルダ
プレースホルダはこんな感じ。
int iLog = 42342;
String sLog = "hgoelog";
logger.warn("■■■ {} プレーステスト {} hoge {} {}",iLog, 5233, sLog, "testlog");

■UTF8日本語文字化け
文字コードutf8でログを出力したいと思っていたら問題発生。eclipse上ではutf8で文字化けなしでいけたのに、何故かjarにしたらsjisで出力されてしまう。下みたいにlogback.xmlに<encoderタグと<charset>タグを追加したら、utf8で出力できた。

<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy.MM.dd HH:mm:ss} [%thread] %-5level %logger{30} - %msg%n</pattern>
</layout>
<charset>UTF-8</charset>
</encoder>

■ログファイル名に日付を入れてログローテしたい時。

こんな感じ?初日はtestbacklog.logしか作られないから数日間様子見する。
<file>/test/testbacklog.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>testbacklog_%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>200</maxHistory>
</rollingPolicy>

ここ が参考になる。

■あるライブラリ内部でjava.util.loggingを使ってログを標準出力している場合、JDKからSLF4j経由でLogbackへログ出力を委譲したい時について。

slf4jのjul-to-slf4j-1.7.5.jarが必要。

mirageなどのormはpureJava(util.loggin)を使って、sqlログを標準出力している。このログをSLF4jでハンドリング、委譲したい。

SLF4JBridgeHandlerを使い、main文の最初に以下を書く。

SLF4JBridgeHandler.removeHandlersForRootLogger(); // (since SLF4J 1.6.5)
SLF4JBridgeHandler.install();

この二行だけでできる。util.loggingのsqlログは標準出力で赤字だったけど、黒字に変わるから変化にすぐ気づく。また、設定ファイルでもできるらしい。ここ が参考になる

■ほか
・標準出力にはログレベルWARN以上、ログファイルにはINFO以上を出力したい時は?
・アスペクトがしたい。メソッド実行前後のログとか。他のライブラリも必要?
・ログ出力ファイルを掴んでいるとログが出ない。エラーも出ない

■参考
logback
java好き(SLF4J+LOGBACK)
SLF4jとLogbackでログ出力してみたよ
・コピペで始めるSLF4J&Logback
SLF4J - Javaロギング実装・ライブラリの柔軟な切り替え・効率化を実現するロギング Facade
mirageのインストールとSLF4Jの設定