はじめに
うう。。百合子。。これが恋の味。。。。 nikkieです
logbackを触る中で読んだドキュメントから興味深い点を書き留めます。
Pythonのlogging標準モジュールによるロギングは知っていて、Javaのlogbackを知っての感想といった趣です。
目次
Chapter 2: Architecture
logbackのドキュメント、分量は多いですが、ここから読んでいってよかったと感じています(あくまでロギングに経験がある場合の意見)。
additivityを知れたのもこのドキュメントに目を通していたからというのがあります。
logbackには3つのモジュール
classicはSLF4Jと合わせて環境構築したときに設定していましたね。
Logback-classic natively implements the SLF4J API so that you can readily switch back and forth between logback and other logging systems such as log4j or java.util.logging (JUL) introduced in JDK 1.4.
ドキュメントではlogback-classicに焦点を当てていきます。
Logger
Logger context
ロギングのよさはprintと違って、あるログステートメントは無効にできる点にあると述べられています。
ここに関連した仕組みの説明が続きます。
まずロガーの名前による階層構造(仕組みに関わっていくことが徐々に分かります)。
com.fooロガーとcom.foo.Barロガーはcom.fooが親となります。
A logger is said to be an ancestor of another logger if its name followed by a dot is a prefix of the descendant logger name.
Effective Level aka Level Inheritance
ロガーはレベルを持ちます(開発者が割り当て可能)。
ロガーのレベルに階層構造が関係します。
If a given logger is not assigned a level, then it inherits one from its closest ancestor with an assigned level.
意訳 ロガーにレベルが割り当てられていないとき、そのロガーは、レベルが割り当てられている最も近い祖先からレベルを継承する
そして、すべての親ルートロガーはデフォルトでDEBUGレベルが割り当てられています。
ドキュメントの例が分かりやすかったです。
1つ紹介すると
- ルートロガー:DEBUGレベル
- ロガーX:レベルを割り当てていないとき、レベルを割り当てられている一番近いロガー(=親のルートロガー)と同じDEBUGレベルとなる
- ロガーX.Y:レベルを割り当てていないとき、レベルを割り当てられている一番近いロガー(=ルートロガー)と同じDEBUGレベルとなる
Printing methods and the basic selection rule
先の無効化の話が完全回収されます。
レベルによってログを無効にできる仕組みの紹介です。
Basic Selection Rule
A log request of level p issued to a logger having an effective level q, is enabled if p >= q.
例えば、ログリクエストをp=INFOレベル、ロガーをq=DEBUGレベルとしたとき、INFO >= DEBUG (p >= q) が成り立つので、ログは有効です。
pとqを入れ替える(INFOレベルのロガーのdebug()メソッド呼び出し)と、ログは無効になります
ドキュメントには、pとqを列挙した表があります。
ロガーについてその他
2点メモです。
(1) ロガーの名前が同じであれば、同じロガーオブジェクトへの参照を返す
Calling the LoggerFactory.getLogger method with the same name will always return a reference to the exact same logger object.
ロガーの名前ごとにシングルトンってことですかね。
(2) ログステートメントの書き方について
https://logback.qos.ch/manual/architecture.html#parametrized
logger.debug("The entry is {}.", entry);
ログリクエストが有効なときのみ文字列中の{}の部分が評価されるので効率がよいと理解しました。
他の書き方
alternativeとのことです(常に評価されないと理解)
if(logger.isDebugEnabled()) { logger.debug("The entry is " + entry + "."); }
常に評価されるためにあまりよくない書き方
logger.debug("The entry is " + entry + ".");
Appender
additivityは先日記事にしました。
https://logback.qos.ch/manual/architecture.html#additivity
もう1つLayoutという要素があるのですが、今のところ必要になっていないので後回しとします。
Pythonのloggingと比べて(雑感)
- Pythonのloggingのロガーにも階層構造があります。aはa.bの親となるので、logbackと同じですね
- すべての親、ルートロガーもあります
- logbackのappenderはPythonだとハンドラという概念に近い
- Pythonでは子のロガーへのログリクエストが有効なとき、親のロガーにpropagate(伝播)させる(これはlogbackにはない)
- 細かいですが、ログのレベルの内訳は違います
終わりに
logbackのArchitectureのドキュメントで興味深かった点を書き出しました。
公式ドキュメント、分量は多いですが、logbackを正確に大まかに理解するのに役立ったと思います。
すでに知っていたPythonのloggingと比べて違う点があるのは面白いですね(appenderとハンドラ)