DoorKeeper
https://jjug.doorkeeper.jp/events/32477
Togetter
http://togetter.com/li/886876
場所は日本オラクルです。
参加者は100人以上だったようです。私が定刻に会場に着いた時、既にほぼ満席で、最前列に座る羽目に・・・
前半のテーマは「ログ」。エンジニアなら、
- なんでこんなに似たようなライブラリがあるん?
- どこがどう違うん?
- どれ使ったらええのん?
で、ずっとモヤモヤしてたんですが、この勉強会の告知を見てピキーンとなり、速攻申し込んだのでした。
あと、後半のせとさんはあちこちの勉強会でよくご一緒させてもらってます。
先日の@t-wadaさんの横浜道場TDDの講演、せとさんも私もちょうど聴講してたんですが、これを受けてせとさんがどういうセッション構成にしてくるのか楽しみでした。
以下、個人メモ。
■ Javaのログ出力: 道具と考え方
■ ログの語源
- log = 丸太
- 帆船の時代、丸太(log)は船の速度標として使われていた。
■ ログ vs デバッガ
- マルチスレッド環境とかだと、再現するのが難しい故障とか発生する。
- その場合はデバッグが難しいので、ログで発生状況を分析する。
■ ログの道具
- Javaのログライブラリはたくさんあって、列挙されたライブラリのうち、Log4j2以外はどれもそこそこ使われている。
■ 役割が異なるライブラリ
- (A)~(D)のうち、SLF4Jだけが「ログファサードライブラリ」で、残りの3つは「ログ出力ライブラリ」。
- 「ログファサードライブラリ」は、「ログ出力ライブラリ」の前にいる。
- (B),(C),(D)は同じ人が作った。(A)だけグラハムさんが作った。
■ ログ出力の階層
- アプリがログを書くときに、直接ログライブラリを叩かない場合があって、間にログファサードライブラリをかます。
- ログファサードライブラリはログ出力ライブラリに処理を委譲する。
■ Javaログライブラリの歴史
- 1999年までは、これといったログライブラリがなかった。
- Apache Tomcat 3.0では、ログ出力にSystem.err.printlnを使っていた。
- ソースのコメントに、「これはやっつけの実装だから修正しなければならない」と書いてあったらしい。
- Tomcatは、後にログライブラリを中に持つことになった。
- 1999年にLog4jが登場した。今に至るまで、一番よく使われているログ出力ライブラリ。
■ 階層化されたロガー
- ロガーは、プログラムからログを出力するのを受け持つ。
- アペンダは、プログラムから渡されたログのテキストを外部リソースに書き込む。
- ロガーとアペンダは、くっつけたり外したりできる。
- Log4jも、ドット区切りのロガー名で階層化されている。
- ログ書き出し元をログ名にする。
- ロガーは親の設定を継承するのが基本。子は親の機能を継承する。子で親の設定を上書きできる。
■ MDC
- 実行時文脈の値をいれておくスレッドローカルなHashMap。
- MDCは便利なので覚えてください。
- MDCは、文脈情報を覚える。MDCを使えば実行時文脈をログに出せる。
■ java.util.logging
- 2000年に規格化を開始。
- ソースコードも、Log4jと比べ2箇所しか変わらず、だいたいおなじ。
- java.util.loggingよりもLog4jのほうが、ずっと長く使われた。
- java.util.loggingのログレベルには、CONFIGという謎のレベルがある。
- CONFIGとINFO、どっちがシビアやねん!あと、FINE, FINER, FINESTもよくわからん。
- 日本語のログが面白いので、試すのおすすめ。
- 1つのログが2行で出力されるので、使いにくい。
- JVM全体で1つの設定しか持てない。Log4jなら、アプリ毎にLog4jのjarを突っ込めばいけた。
■ Commons Logging
- 2001年に登場した便利ライブラリ。
- 特定のログ実装に依存するのはちょっと嫌だから、間に1個かまそう、という理由で始まったログファサードライブラリ。
- でも、Log4jやjava.util.loggingの切り替えには上手く使われなかった。
- SpringもCommons Loggingも採用しているが、正直イケてない。
- ログ実装の選択方法がぶっこわれてる。
■ Commons Logging 実現したかったこと
- アプリごとに設定を変えてログを出力したい。
- どういうアプローチを取ったかというと、Context ClassloaderというJavaの仕組みを使った。
- Classloaderと戯れたことがある人なら分かるが、辛い・・・。大失敗した。
- Java EEコンテナでは、クラスローダ不一致によりNoClassDefFoundErrorが頻発した。
- Eclipseとかが使ってるOSGiコンテナは、Context Classloaderを使ってないので、そもそも動かない。
- 以上より、Commons Loggingは"失敗"といえる状況。
■ SLF4J
- Simple Log Facase for Java
- Logbackはログ出力ライブラリだが、自前のログインタフェースを持たない。SLF4Jと組み合わせて使う前提。
- Log4jとだいたい同じだが、ログメッセージの引数にプレースホルダーが使えるようになっている。
- プレースホルダーで文字列連結がいらなくなるので、若干計算量が減る。
- クラスを動的に探索するのではなく、差し替えで静的バインディングする。
- ログの横取りをする仕組み。
- 2種類のjarが必要。他のログ実装へのバインディングのjarを、API(必須)のjarと組み合わせて使う。
- SLF4Jの静的バインディングの中身で、StaticLoggerBinderは5つか6つの実装がある。
- ハードコーディングで静的にバインディングする。
- ログを横取りするためのjarが個別に用意されている。
- Log4jのクラスを呼んでいるようで、SLF4Jのクラスを呼ぶ。
■ Logback
- 独自のロガーインタフェースを持たず、SLF4J経由で呼び出す。
- 提供する機能に、「マーカー」がある。
■ Log4j2
- Logbackのプレースホルダーが使える。
■ 使うべきログ関連ライブラリ
- 共有ライブラリを作る場合は、SLF4Jにログを出すのが一番賢いやり方。
- MavenとかGradleとか使うとき、コンパイルスコープではログ実装ライブラリに依存しないようにすべき。
- testCompileの方にLogbackのjarを依存性として書く。
- アプリケーションを使う場合は、制約がなければ SLF4J+Logback が無難。
■ まとめ
- Log4jは凄い。
テスト駆動開発ここが聞きたい
TDDでお馴染み、せとさんのお話。せとさんの講演は何度か聞いたことありますし、せとさん主催のGOOS読書会にも出てました。
この日はTDDについて、テクニカルなネタよりもエモい要素を多めに、いろんな観点から説明されています。
ログの講演は個人的に初物だったので勉強も兼ねてメモ取りながら聞いてましたが、そんなわけで、せとさんの講演の方はゆったり聴講させていただきました。
個人的には、「組織パターン」の最初に出てくる「信頼で結ばれた共同体」という話が興味深かった。
せとさん曰く、これ読むだけでも価値があるとのこと。
あと、ハッとさせられたのが
「その場に居続けるには全力で走り続けなければならない」
というフレーズですね。鏡の国のアリスからの一節らしいですが、エンジニアの世界にもそのまんま当てはまる言葉です。
★感想:
これまでログライブラリは、いろいろあるなぁと思いつつなんとなく使ってたんですが、この日の講演を聞いてすごく整理された。
複数のログライブラリを時系列で追っていくのは、ライブラリの背景とか互いの関係性がよくわかりますね。
あとTDDですが、先日の@t-wadaさんの講演の聞いた後にすぐ今回のせとさんということで、講演内容と主張を比較しながら考える良い機会になりました。
19:00~20:50 #jjug 20:50~21:05 移動 21:05~22:05 「理論から学ぶ データベース実践入門」読書会 たまたま近場だったけど、案外、勉強会のハシゴも行けるもんだな・・・
— makopi23 (@makopi23) 2015, 10月 14
これだけ勉強会三昧な1日は初めてかもしれない。
登壇者さん、JJUG関係者のみなさま、ありがとーございました。