吉村 武志 (@takesi_yosimura)
あるかも・・・
あるかも・・・
ログは起きた事の記録なので、
後から追跡する用途のためのもの
これを踏まえて・・・
日時
発生箇所(ファイル・行・クラス・メソッドなど)
出力抑制機能(本番でデバッグログ出さないなど)
・・・・・・
名称 | 登場時期 | 備考 |
---|---|---|
log4j | 1999年 | 2015年にEOL |
java.util.logging | 2002年(java1.4) | 残念なJava標準 |
Apache Commons Logging | 2002年 | ログファサードライブラリ |
SLF4J / LOGBack | 2006年 | 今のデファクト? |
Log4j2 | 2014年 | 1系と互換性の無いLog4j |
private final Logger logger = Logger.getLogger(getClass());
public void log4jTest() {
this.logger.info("情報ログテキストを出力");
}
当時のデファクトスタンダード
ロガーで出力先(アペンダ)制御
アペンダで多様な出力先を実現(ファイル以外も可)
ログレベルで出力抑制制御
ロガーの階層化
この後のログライブラリもだいたいLog4J互換らしいので、 Log4Jについてもうちょい詳しく見ていきます。
private final Logger logger = Logger.getLogger(getClass());
だいたい上の例のように、Logger.getLogger(String name)の 引数にクラス名を渡して取得します。
このloggerに生えたメソッドを使ってログを出力します。
public void log4jTest() {
this.logger.fatal("致命的エラー");
this.logger.error("エラー");
this.logger.warn("警告");
this.logger.info("情報");
this.logger.debug("デバッグ");
this.logger.trace("トレース");
}
上記の6つはいずれもログ出力用メソッドです。
上の方から順に出力優先度が高いです。
public void log4jTest() {
for(int i=0; i < 10000; i++) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("デバッグ:" + i);
}
}
}
Log4J登場当時は可変長引数が無かったので、
文字列結合コスト削減でこんなメソッドも使いました。
### ログメッセージを標準出力に出力するアペンダ「stdout」 ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %5p %c{1} - %m%n
### ログメッセージを test.log に出力するアペンダ「logfile」 ###
log4j.appender.logfile=org.apache.log4j.RollingFileAppender
log4j.appender.logfile.File=test.log
log4j.appender.logfile.Append=true
log4j.appender.logfile.MaxFileSize=1MB
log4j.appender.logfile.MaxBackupIndex=3
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %5p %c{1} - %m%n
### 名前が「logtest.***」であるロガーからのアペンダは「stdout」と「logfile」 ###
log4j.logger.logtest=info, stdout, logfile
上の例のように「アペンダ」を定義し「ロガー」に設定。
上の例はlog4j.propertiesですが、XML形式でも書けます。
アペンダを変えればいろいろ出力可
出力書式も好きに書ける
スレッド情報なども書式指定だけ
スタック形式のNDC、Map形式のMDCというものがあり、文脈情報を出力可
log4j1.3系は行方不明
private final Logger logger = Logger.getLogger(getClass().getName());
public void loggingTest() {
this.logger.info("情報ログテキストを出力");
}
Java1.4から導入された標準API
ぱっと見Log4Jと似てる
public void loggingTest() {
this.logger.severe("重大");
this.logger.warning("警告");
this.logger.info("情報");
this.logger.config("設定?");
this.logger.fine("デバッグ?");
this.logger.finer("デバッグ?");
this.logger.finest("デバッグ?");
}
ログレベルが謎
標準書式が使いにくい
Java1.3以前で使えない
これは・・・流行らない
private final Log logger = LogFactory.getLog(getClass());
public void loggingTest() {
this.logger.info("情報ログテキストを出力");
}
ログ実装に依存しないログファサードライブラリ
やっぱりLog4Jと似てる
public void loggingTest() {
this.logger.fatal("致命的エラー");
this.logger.error("エラー");
this.logger.warn("警告");
this.logger.info("情報");
this.logger.debug("デバッグ");
this.logger.trace("トレース");
}
あちこちで使われてるらしい
ログレベルはlog4Jといっしょ
動的に探索して、commons-loggingの設定があれば使う
無ければlog4Jやjava.util.loggingを使う
どれも無ければSimpleLog
クラスローダ使って探そうとするので、EE環境等でまともに動かないらしい
動的探索するという構想に無理があったとのこと。
private final Logger logger = LoggerFactory.getLogger(getClass());
public void logbackTest() {
this.logger.info("情報ログ{}を出力", "てきすと");
}
SLF4Jがログファサードライブラリ
LOGBackがログ実装
やっぱりLog4Jと似てる
プレースホルダーが使えてる嬉しい
Log4jを作った人がLog4jに愛想を尽かして作ったとか…
public void logbackTest() {
this.logger.error("エラー");
this.logger.warn("警告");
this.logger.info("情報");
this.logger.debug("デバッグ");
this.logger.trace("トレース");
}
SLF4Jのログレベルはfatalがない
SLF4Jはクラス実体の差し替えとやらで実装との紐付けを実現しているらしい
使うときは正しくjarファイルの配置が必須。
マニュアルを見よう。
%d{HH:mm:ss.SSS} %-5level %logger{10} %msg%n
logback.log
%date %level [%thread] %logger{10} [%file:%line] %msg%n
LOGBackは単独では使えず、SLF4J経由で呼び出す
XMLまたはgroobyで設定を書く
private final Logger logger = LoggerManager.getLogger(getClass());
public void log4j2Test() {
this.logger.info("情報ログ{}を出力", "てきすと");
}
Log4jの1系と互換性の無いLog4j
いろいろ間に合いませんでしたorz
だいたい宮川さんの資料の焼き直しでした!
http://www.slideshare.net/miyakawataku/concepts-and-tools-of-logging-in-java
こだわりが無ければ、SLF4J / LOGBackを使っていれば良さそう
事情がいろいろあったんだなと思ってもらえれば幸いです