ロギングフレームワーク、そしておそらくロギングファサードフレームワークを見たいと思うでしょう。
多くの場合、重複する機能を備えた複数のロギングフレームワークが存在するため、時間の経過とともに多くの人が共通のAPIに依存するように進化したり、ファサードフレームワークを介して使用を抽象化し、所定の場所に交換できるようになったりするようになりました必要に応じて。
フレームワーク
いくつかのロギングフレームワーク
いくつかのロギングファサード
使用法
基本的な例
これらのフレームワークのほとんどでは、次のような形式(ここではslf4j-api
and を使用logback-core
)を作成できます。
package chapters.introduction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// copied from: http://www.slf4j.org/manual.html
public class HelloWorld {
public static void main(String[] args) {
final Logger logger = LoggerFactory.getLogger(HelloWorld.class);
logger.debug("Hello world, I'm a DEBUG level message");
logger.info("Hello world, I'm an INFO level message");
logger.warn("Hello world, I'm a WARNING level message");
logger.error("Hello world, I'm an ERROR level message");
}
}
現在のクラスを使用して専用ロガーを作成することに注意してください。これにより、SLF4J / LogBackは出力をフォーマットし、ロギングメッセージの送信元を示すことができます。
SLF4Jマニュアルに記載されているように、クラスの一般的な使用パターンは通常次のとおりです。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyClass {
final Logger logger = LoggerFactory.getLogger(MyCLASS.class);
public void doSomething() {
// some code here
logger.debug("this is useful");
if (isSomeConditionTrue()) {
logger.info("I entered by conditional block!");
}
}
}
しかし実際には、ロガーを次の形式で宣言するのがさらに一般的です。
private static final Logger LOGGER = LoggerFactory.getLogger(MyClass.class);
これにより、ロガーを静的メソッド内からも使用できるようになり、クラスのすべてのインスタンス間でロガーが共有されます。これは、好みのフォームである可能性が非常に高いです。ただし、Brendan Longのコメントで指摘されているように、その意味を理解し、それに応じて決定する必要があります(これらのイディオムに続くすべてのロギングフレームワークに適用されます)。
ロガーをインスタンス化する方法は他にもあります。たとえば、文字列パラメーターを使用して名前付きロガーを作成する方法があります。
Logger logger = LoggerFactory.getLogger("MyModuleName");
デバッグレベル
デバッグレベルはフレームワークによって異なりますが、一般的なものは次のとおりです(重要度の順に、良性からコウモリの悪い、そしておそらく非常に一般的なものから希望的には非常にまれなものまで)。
TRACE
非常に詳細な情報。ログにのみ書き込む必要があります。チェックポイントでプログラムのフローを追跡するためにのみ使用されます。
DEBUG
詳細な情報。ログにのみ書き込む必要があります。
INFO
注目すべきランタイムイベント。コンソールですぐに見えるはずなので、控えめに使用してください。
WARNING
ランタイムの異常と回復可能なエラー。
ERROR
その他の実行時エラーまたは予期しない状態。
FATAL
早期終了を引き起こす重大なエラー。
ブロックとガード
ここで、いくつかのデバッグステートメントを記述しようとしているコードセクションがあるとします。これは、ロギング自体の影響と、ロギングメソッドに渡すパラメータの生成の両方のために、パフォーマンスにすぐに影響を与える可能性があります。
この種の問題を回避するために、次のようなフォームを作成することがよくあります。
if (LOGGER.isDebugEnabled()) {
// lots of debug logging here, or even code that
// is only used in a debugging context.
LOGGER.debug(" result: " + heavyComputation());
}
デバッグステートメントのブロックの前にこのガードを使用しなかった場合、メッセージが出力されない可能性がある場合でも(たとえば、ロガーがINFO
レベルを超えるもののみを印刷するように現在構成heavyComputation()
されている場合)、メソッドはまだ実行されています。
構成
設定はロギングフレームワークに大きく依存しますが、ほとんど同じ方法でこれを提供します。
- プログラムによる構成(実行時、API経由- 実行時の変更を許可)、
- 静的な宣言的構成(通常、XMLまたはプロパティファイルを使用した開始時- 最初は必要なものである可能性が高い)。
また、ほとんど同じ機能を提供します。
- 出力メッセージの形式の構成(タイムスタンプ、マーカーなど)、
- 出力レベルの構成、
- 詳細なフィルターの構成(たとえば、パッケージまたはクラスを含める/除外する)、
- ログを記録する場所(コンソール、ファイル、Webサービスなど)を決定するためのアペンダーの構成と、場合によっては古いログ(自動ローリングファイルなど)の処理方法。
これは、logback.xml
ファイルを使用した宣言的な構成の一般的な例です。
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
前述のように、これはフレームワークに依存し、他の選択肢がある場合があります(たとえば、LogBackではGroovyスクリプトを使用することもできます)。XML構成形式は、実装ごとに異なる場合もあります。
その他の構成例については、(他のなかでも)次を参照してください。
歴史的な楽しみ
ので、予めご了承くださいLog4Jのは、バージョンからの移行、現時点では主要なアップデートを見ているの1.xに2.xの。より歴史的な楽しみや混乱のために両方を見たいと思うかもしれません。Log4Jを選ぶなら、おそらく2.xバージョンで行くことを好むでしょう。
Mike Partridgeがコメントで述べたように、LogBackは元Log4Jチームメンバーによって作成されたことに注意する価値があります。これは、Java Loggingフレームワークの欠点に対処するために作成されました。また、今後の主要なLog4J 2.xバージョンは、LogBackからいくつかの機能を統合したものです。
勧告
結論として、できる限り分離した状態を保ち、いくつかを試してみて、何が最適かを確認してください。最終的には、単なるロギングフレームワークです。使いやすさや個人的な好み以外に、非常に具体的な理由がある場合を除いて、これらのいずれかがかなりうまくいくので、それにぶら下がることは意味がありません。それらのほとんどは、ニーズに合わせて拡張することもできます。
それでも、今日組み合わせを選択する必要がある場合は、LogBack + SLF4Jを使用します。しかし、数年後に私に尋ねた場合、Apache Commons Loggingを備えたLog4Jをお勧めしていましたので、依存関係を監視し、それらとともに進化してください。