Javaロギングガイド:基本
アルファン・シャリフ - 2023 年 2 月 13 日
ログを記録すると、アプリケーションがどのように実行されるか、または何かが失敗したときに何が問題になったかを理解するのに役立ちます。 この情報は、デバッグや監査の目的で重要になる可能性があります。 ログはプログラム実行中のすべてのイベントの証跡を維持し、それらの記録を後で分析できるようにします。
ただし、効果的なロギングは自動的には行われません。 アプリケーション開発者は、アプリケーションが重要な詳細を処理しやすい形式で体系的に記録していることを確認する必要があります。
ロギングへの最も基本的なアプローチは、print ステートメントを単純に使用して、必要なアプリケーションの詳細を表示することです。 もちろん、これは次の理由から理想的なアプローチではありません。
これらすべての理由から、Java などの多くのプログラミング言語には、専用のロギング API とフレームワークが含まれています。 この概要 (シリーズの最初の部分) では、Java アプリケーションの基本的なロギング概念を紹介します。 ロギング オプションを見てから、利用可能ないくつかのロギング フレームワークとそれらがサポートする構成について検討します。
完全な Java ロギング ガイド シリーズをご覧ください。
アーキテクチャ内の他のすべてのものと同様に、Java はログ記録に対して拡張可能でカスタマイズ可能なアプローチを採用しています。 java.util.logging フレームワークは、すべてのロギング関連関数のデフォルト オプションです。 このフレームワークは、ロギングに必要なすべての基本機能を提供すると同時に、サードパーティのフレームワークによるそれらの機能の拡張を可能にします。
このロギング フレームワークには、次の 3 つの主要なモジュールが含まれています。
ここで注目に値するもう 1 つの概念はフィルターです。 フィルターを使用すると、開発者は LogRecord をインターセプトし、どのハンドラーを使用するかを決定できます。 基本的なロギングには不要ですが、フィルターは複雑なロギング要件を満たすのに役立ちます。
Java のロギング フレームワークの場合、デフォルトの出力場所はユーザーのホーム ディレクトリです。
Java のロギング フレームワークはすべての基本機能を提供しますが、サードパーティのフレームワークはロガー、ハンドラー、およびフォーマッタを組み合わせることでかなりの機能を実行できます。 Log4j 2 と Logback は 2 つの人気のあるロギング フレームワークであり、それぞれに独自の長所があります。
Java では複数のフレームワークが利用可能であり、それらの機能セットは常に進化しているため、開発者は多くの場合、別のものを試したいと考えます。 ここでロギングアブストラクタが活躍します。 アブストラクターを使用すると、開発者は標準の関数仕様を使用してロギング フレームワークをすばやく切り替えることができます。 Simple Logging Facade for Java (SLF4J) は、デフォルトのフレームワークである Log4j 2 および Logback をサポートする一般的なロギング アブストラクターです。 Apache commons-logging もそのような抽象化ツールです。
ただし、パッチが適用されていないバージョンの Log4j 2 は重大なセキュリティ リスクを引き起こすことに注意することが重要です (CVE-2021-44228)。 それほど深刻ではありませんが、Log4j 1.x (CVE-2021-4104) および Logback (CVE-2021-42550) にも重大なセキュリティ リスクが存在します。 アブストラクターの使用は依然としてこれらの基礎となるフレームワークに依存しているため、安全に使用するには、これらの脆弱なライブラリを適切に更新し、パッチを適用することが不可欠です。
デフォルトのフレームワークは、構成ファイルを使用してアペンダー、ロガー、レイアウトの詳細を定義します。 デフォルトでは、このファイルは Java インストール ディレクトリの lib フォルダに存在しますが、これはグローバル構成ファイルです。
アプリケーション固有の構成ファイルを定義することをお勧めします。 これを行うには、次に示すように、アプリケーションの起動時にプロパティ ファイル名を指定します。
単純な構成ファイルは次のようになります。
ここで、構成は、ユーザーのホーム ディレクトリに作成されるファイルにアプリケーション イベントを記録します。 値 %h はホーム ディレクトリを示し、%u はログ ファイルを区別するために Java が設定する任意の一意の番号を示します。
ここで、新しいクラスから新しいログファイルを作成するには、以下のコード スニペットを使用できます。
いつ、何をログに記録するかは完全にアプリケーション開発者次第であり、アプリケーション チームが採用するログ戦略によって異なります。 開発者がログに記録するイベントを決定したら、ログには 1 行のコードが必要になります。 以下に例を示します。
ここで、スニペットは logger.log メソッドを使用してログ イベントを永続化します。 このメソッドは、ロガー レベルの設定とログに記録されるテキストという 2 つの入力を受け取ります。
他の 2 つの方法を使用して、ログ イベントを永続化できます。 logp メソッドは、クラスと関数の名前をテキストとともにログに記録します。 logrb メソッドを使用すると、ローカライズ用のリソース バンドルを指定できます。 これは多言語アプリケーションにとって重要です。 どちらの方法もログ方法の代わりに使用できます。
ロギング フレームワークは、5 種類のハンドラー (したがって、5 種類の宛先) をサポートします。 これらはプロパティ ファイルまたはコードで簡単に構成できます。 これら 5 つのハンドラーを調べて、それらがどのように使用されるかを見てみましょう。
コンソールハンドラ:名前が示すように、これはログ イベントをコンソールに出力します。 ここには出力を永続化するメカニズムはありません。 コンソールが終了すると、すべてのログ エントリが失われます。 プロパティ ファイルでハンドラーを指定できます。
FileHandler: このハンドラーはログをファイルに書き込みます。 このハンドラーを使用すると、ログ ファイルが特定のサイズに達したときに、ログ ファイルをローテーションできます。 以下のスニペットは、プロパティ ファイル内の特定のパラメーターとともに、このハンドラーを設定する方法を示しています。
limit パラメータは、新しいログ ファイルが作成される最大ログ ファイル サイズをバイト単位で定義します。 append パラメータは、ファイル名が存在する場合に追加を許可するかどうかを指定します。 pattern パラメータはログ ファイル名を定義します。
SocketHandler: このハンドラーは、HTTP ソケットにログを書き込みます。 これは、既に実行されているもの以外の別のインスタンスまたはサービスにログを保存する必要がある場合に便利です。 ここで使用されるデフォルトの形式は XMLFormatter です。
StreamHandler: このハンドラーは、後で任意の宛先に書き込むために使用できる OutputStream に出力を書き込みます。 このハンドラーは、別の宛先に基づくカスタム ハンドラーを定義する必要がある場合の基盤として機能する基本クラスです。 定義は、プロパティ ファイルでハンドラーを設定するのと同じくらい簡単です。
MemoryHandler: このハンドラーは、すべてのログ エントリをメモリ内の循環バッファに書き込みます。 受信レコードのレベルが事前定義されたものよりも高い場合、または特定の条件を満たす場合、メモリ バッファに書き込みます。 これらの条件は、ログ関数をオーバーライドするクラスを実装することでカスタマイズできます。 新しい関数はすべてのレコードをスキャンし、いつ書き込むかを決定できます。 このハンドラーは、パフォーマンスの観点からは、バッファリングは安価ですが、フォーマットにはコストがかかるため、よく使用されます。 このハンドラーを使用すると、書き込みが必要になるまでフォーマットのコストが延期されます。
ハンドラーは、サードパーティのロギング フレームワークがデフォルトのロギング API よりも優れた機能を発揮する領域の 1 つです。 たとえば、Log4j 2 は、企業セットアップで一般的に使用される多数のハンドラーを提供します。 たとえば、SysLogAppender は、オペレーティング システム ログ (syslog など) またはログ集約サーバーにエントリを書き込みます。
ログ レベルは、開発者が重要度に応じてログを分類するのに役立ちます。 これは、開発、ステージング、実稼働など、さまざまな環境を通じてコードを移行するときに非常に役立ちます。 開発環境では、開発者はデバッグやテストのためにできる限りすべての情報を取得したい場合があります。 コードが運用環境にデプロイされたら、運用チームは重大なログ イベントについてのみ通知を受ける必要がある場合があります。 Java ロギング フレームワークは 7 つのロギング レベルをサポートしています。 通常、アプリケーションでは、重大度の高い順に次のものが使用されます。
Logger クラスの初期化時にログ レベルを設定すると、開発者がそのレベル以下のすべてのログをフィルターで除外するのに役立ちます。 たとえば、ログ レベルが INFO に設定されている場合、INFO、WARNING、または SEVERE のタグが付いたイベントのみが出力されます。 簡単なコマンドでログ レベルを設定できます。
ログ機能を使用すると、永続的なログ エントリのレベルを定義できます。
概要の最初の部分では、Java のデフォルトのロギング フレームワークの基本について説明しました。 このフレームワークはアプリケーション レベルのロギングに必要なすべての基本機能を提供しますが、高度な機能では開発者がカスタム ハンドラーを作成する必要があります。 Log4j 2 や Logback などのサードパーティのログ フレームワークにより機能セットが拡張され、開発者がカスタム開発を行う必要がなくなります。
このシリーズのパート 2 では、例外処理、フォーマッタ、ログ集計など、Java ロギングの高度な概念について学びます。
Arfan Sharif は、CrowdStrike の可観測性ポートフォリオの製品マーケティング リードです。 彼は、Splunk、Genesys、Quest Software などの企業でログ管理、ITOps、可観測性、セキュリティ、CX ソリューションを推進してきた 15 年以上の経験があります。 Arfan はバックス アンド チルターンズ大学でコンピュータ サイエンスを卒業し、製品マーケティングとセールス エンジニアリングにまたがるキャリアを持っています。
Java ロギング ガイド Java ロギング ガイド シリーズ全体を参照してください: ロガー: ハンドラー: フォーマッタ: ConsoleHandler: