Article by: Abdul D
なぜロギングとデバッグが重要なのか?
プログラムの開発中、プログラムの実行フローを追跡し、コード内の問題を特定するために、単純な println() ステートメントを使っているかもしれません。しかしプロジェクトが大きくなり、複雑になるにつれて、プリント文はすぐに散らかってしまいます。プログラムの実行を追跡するためのより良い方法はロギングです。ロギングはアプリケーションの動作を一貫して整理された方法で追跡する手段を提供し、問題を体系的に特定し、解決できるようにします。
このガイドでは、Java でのロギングの設定方法、基本的なデバッグツールを効果的に使用する方法、そして安定した保守可能なアプリケーションを作成するためのベストプラクティスについて探ります。
また、Sentry が Java アプリケーションでエラーを監視し管理する手助けをどのようにするかについても見ていきます。基本と合わせて、高度なテクニックを理解することで、Javaプロジェクト内の問題に自信を持って取り組むための準備が整います。
Java でロギングを設定する方法
もしかするとコードのロギングとデバッグのために System.out.println() を使用したことがあるかもしれません。
次のように出力されます。
Debugging: Starting the program
Debugging: Result is 8
このようなコンソールロギングは、小規模なプロジェクトや簡単なテストには役立つことがありますが、いくつかの制限があります。保存されていないコンソールログはプログラムが停止すると消えてしまい、何が起こったのかの履歴を保持することが難しくなります。また、ログメッセージを重要度別に分類することができず、出力結果で重要な問題を見逃しやすくなります。
Javaでの基本的なロギングは、組み込みの java.util.logging パッケージを使用することで実現できます。この組み込みフレームワークを使用すると、アプリケーション内で情報メッセージ、警告、エラーなど、さまざまなイベントを簡単に記録して出力できます。
java.util.logging を使用すると、各メッセージの重要度を示すためにログレベルを指定できます。
- SEVERE:アプリケーションが正しく動作しない可能性のある重大なエラーを示します。
- WARNING:注意が必要な潜在的な問題を示します。
- INFO:アプリケーションの実行進行状況に関する一般的な情報を提供します。
- CONFIG:設定関連のメッセージを示します。
- FINE, FINER, FINEST:デバッグ目的で詳細な情報を提供します。
これらのログレベルは次の構文を使って使用できます。logger.<LEVEL>(“<YOUR_MESSAGE_HERE>”)
ロギングを有効にするには、module-info.java ファイルに以下を追加する必要があるかもしれません。
requires java.logging;
以下はロガーを設定し、異なるレベルでメッセージをログに記録する方法です。
以下が出力されます。
ロギング例の出力
ログメッセージがタイムスタンプで記録され、ログステートメントが呼ばれたクラス名とメソッド名が含まれている点に注目してください。この情報は、複雑なアプリケーションでバグを追跡する際に非常に貴重です。
Javaでのログレベルの設定
上記の例では、INFO、WARNING、SEVEREメッセージのみがログに記録され、CONFIG と FINE メッセージは記録されていないことに気付くかと思います。 これはデフォルトのログレベルが INFO に設定されているためです。つまり、INFOレベル以上のメッセージのみが記録されます。
ログレベルの階層に戻ると…
- SEVERE
- WARNING
- INFO:このレベル以上のメッセージのみがデフォルトでログに記録されます。
- CONFIG
- FINE
- FINER
- FINEST
ログレベルを変更して、どのメッセージを記録するかを制御することができます。例えば、FINE レベル以上のメッセージをログに記録するには、ConsoleHandler を使用してログレベルを FINE に設定できます。
これで出力には FINE と CONFIG メッセージが含まれます。
FINEレベルでのロギング例の出力
Java でファイルにログを記録する方法
ログをファイルに保存することもできます。これにより、アプリケーションの動作の永続的な記録を保持し、将来の分析に役立てることができます。ログをファイルに保存することで、アプリケーションが停止した後でも問題を追跡しやすくなり、異なる実行からのログを比較して、異なる設定間でのパターンを特定することができます。
前の例を拡張して、ログメッセージをファイルに保存する方法を見てみましょう。FileHandler クラスを使用して、application.logという名前のファイルにログを記録します。
このコードを実行すると、ログメッセージはプロジェクトディレクトリ内の application.log という名前のファイルに保存されます。その後、このファイルを開いてログを確認できます。
ログファイルの内容のスクリーンショット
Java での変数と例外のロギング
デバッグ時にはアプリケーションの特定の時点での状態を理解するために、変数や Java での例外の値をログに記録することが役立つことがあります。
例えば二つの数字を割るメソッドがあり、割られる数字の値をログに記録したいとしましょう。
次のように出力されます。
2024-11-18 14:30:00 INFO LoggingVariablesExample: Dividing 50 by 10
2024-11-18 14:30:00 INFO LoggingVariablesExample: Result: 5
ゼロで割る際に発生する例外をログに記録し、スタックトレースも表示したい場合、b 変数の値を 0 に変更します。
次のように出力されます。
スタックトレースがログメッセージに含まれていることに注目してください。これにより、例外が発生した場所を正確に把握することができます。
Java の例外処理について、さらに詳しく知りたい方はこちらで完全な解説を行っています。
Javaにおけるロギングのベストプラクティス
以下は、覚えておくべきベストプラクティスです。
最適なログレベルを設定する
ログは修正が必要な重要なエラーを追跡するために使用できる際に役立ちます。特定のアプリケーションに応じて、最適なログレベルを設定してください。あまりにも多くのイベントをログに記録すると、デバッグの観点からは最適ではありません。なぜならログをフィルタリングして、即座に対応が必要なエラーを特定するのが難しくなるからです。
機密情報のログ記録を避ける
パスワードやAPIキー、個人情報などの機密情報をログに記録する際は慎重に扱ってください。
デバッグを容易にするためにログファイルをローテーションする
複数のモジュールを持つ、大規模なアプリケーションのログファイルは大きくなる可能性があります。ログファイルを定期的にローテーションすることで、このようなアプリケーションのデバッグを容易にすることができます。ログファイルをローテーションするには、最大ファイルサイズや時間間隔を設定し、その後に新しいログファイルを作成するようにします。これにより、最新のログファイルを見て問題を簡単に特定できます。
例えば、以下の構文で FileHandler を設定できます。
現在のファイルが指定されたサイズに達したときに、新しいログファイルを作成し、指定された最大ファイル数まで、ログをローテーションします。
ログのフォーマットを使用してログをより読みやすくする
ログのフォーマットを使うことで、ログをより読みやすく、一貫性のあるものにすることができます。フォーマッターを使用して、ログメッセージのフォーマットをカスタマイズできます。例えば、タイムスタンプ、ログレベル、クラス名、メッセージを特定のフォーマットで含めることができます。
これにより、ログメッセージは秒単位のタイムスタンプ、ログレベル、およびメッセージを含む形式でフォーマットされます。
Java デバッグ 101 – Eclipse でのデバッグ方法
Java のデバッグは、コードの問題を特定して修正するためのツールと技術を含みます。ブレークポイントを効果的に使用し、変数を調べ、コードをステップ実行する方法を理解することが、より速くデバッグするための鍵となります。
では、Eclipse で割り算の例をデバッグしてみましょう。Eclipse は最も人気のある Java IDE の一つで、バグを見つけて解決するための強力なデバッグ機能を提供します。
次のコードをデバッグします。このコードには、b が x + x ではなく x – x に設定されるというエラーがあります。
仮に、変数 b の値を x + x で設定したいと思ったが、誤って x – x で値を設定してしまったとしましょう(上記のコードのように)。これにより、変数 b にはゼロが格納されます。この値が divide メソッドの y 引数として設定され、ゼロ除算エラーが発生します。
スタックトレース
divide() 関数はゼロで割ろうとしたときに ArithmeticException をスローします。理想的にはこのケースを処理するために例外ハンドラを追加したいですが、デバッグの目的では問題を特定し、一時的に修正することに焦点を当てます。
プログラム実行のスタックトレースが、エラーが発生したコードの行を示していることに注目してください。これにより、この行にブレークポイントを設定してデバッグを開始できます。
Eclipse でこの例をデバッグする方法
1. ブレークポイントを設定する
コードエディタの左の余白をクリックしてブレークポイントを設定します。ブレークポイントはデバッガーに、特定の行でプログラムを一時停止するよう指示するマーカーです。上記のコードでは、int answer = x / y; の行にブレークポイントを設定します。これにより、ゼロ除算が発生する前にプログラムを一時停止できます。
ブレークポイントを設定する
2. プログラムをデバッグモードで開始する
バグのアイコンをクリックし、プログラムをデバッグモードで開始します。これにより、コードはブレークポイントまで実行され、プログラムの状態を確認できます。
デバッグモードの開始
3. ブレークポイントで変数を調べる
プログラムがブレークポイントで一時停止すると、変数ビューで変数の値を調べることができます。この場合、 y の値が 0 であることに気付き、ゼロ除算エラーが発生しています。
変数の調査とコードのステップ実行
4. 問題を一時的に修正する
変数ビューのペインで、y の値を10(5 + 5)に直接変更することで、一時的に問題を修正し、プログラムの実行を再開して結果を確認します。
問題の一時的な修正
「Resume」ボタンをクリックすると、一時的に修正した後、プログラムの実行が続行されます。これにより、ゼロ除算エラーを回避して結果を見ることができます。
「Resume」ボタンをクリックしてプログラムの実行を再開する
その後、b の値をゼロに設定し、y 引数がゼロの値を保持する原因となったコードを修正できます。コードを int b = x – x; から int b = x + x; に変更し、プログラムを実行して修正された出力を確認します。
一時的な修正後の修正された出力
この例から分かるように、デバッグはコード内の問題を特定し、プログラムの動作を理解し、正しく実行されるように必要な修正を行うことを可能にします。
サードパーティの Java ロギングライブラリの使用
組み込みの java.util.logging パッケージは基本的なロギングニーズには十分ですが、サードパーティのロギングライブラリは、より複雑なプロジェクトにおいて役立つ追加機能と柔軟性を提供します。
Java エコシステムで人気のあるロギングライブラリには、Log4j と Logback があります。これらのライブラリは、複数の宛先へのロギング、ログメッセージのフィルタリング、ログレベルの動的な設定などの機能を提供します。
これらのライブラリと、それらを Java プロジェクトに統合する方法について詳しく学ぶには、公式ドキュメントを参照してください:
Sentry は両方のライブラリとの統合を提供しています。Log4j および Logback でSentryを設定する方法については、ガイドを参照してください。
Sentry が Java のロギングとデバッグにどのように役立つか
Sentry はリアルタイムで問題を追跡し、アプリケーションで発生するエラーに関するインサイトを提供します。Sentry を Java アプリケーションに統合することで、エラーをキャッチし、パフォーマンスを監視することができます。
始めるには、Sentry Java SDK をプロジェクトに追加し、データソース名(DSN)を使用して設定する必要があります。
DSN は Sentryダッシュボード でプロジェクトを作成し、[Your-Project] > プロジェクト設定 > クライアントキー(DSN)に移動することで取得できます。
Maven を使用してSentryをプロジェクトに追加する方法は次の通りです。
pom.xml ファイルに以下の設定を追加します(値はご自身のものに置き換えてください)。
Sentry for Java の設定に関する詳細な手順については、Sentry の Java ドキュメントを参照してください。
では、先ほどの割り算プログラムに Sentry を統合する方法を見てみましょう。
アプリケーションをDSN値で設定した後、Java アプリケーションを実行すると、エラーはすべて Sentry プロジェクトにログされます。
Sentryでキャプチャされた例外
エラーがキャプチャされると、Sentry ダッシュボードに移動して、エラーの報告を見ることができます。報告には、影響を受けたクラス、問題の発生頻度、およびエラーに至るまでのパンくずリストが含まれます。
Sentry ダッシュボード
Sentry は完全なスタックトレースもキャプチャし、コード内でエラーが発生した正確な場所を特定できるようにします。
Sentry を使用することで、未処理の例外を監視し、パフォーマンスの問題を追跡して、コードがスムーズに実行されるように保つことができます。
Sentry でエラーを追跡および管理する
このガイドでは、Java におけるロギングとデバッグの重要性、組み込みの java.util.logging パッケージを使用したロギングの設定方法、そして Eclipse での基本的なデバッグ技術について説明しました。
また、Log4j や Logback のようなサードパーティのロギングライブラリが、複雑なプロジェクトでログを管理するのにどのように役立つかについても見てきました。
最後に、Sentry がどのようにして Java アプリケーションを強化し、リアルタイムでのエラーモニタリングとパフォーマンスインサイトを提供するかについて説明しました。Sentry をプロジェクトに統合することで、エラーを効果的に追跡および管理し、アプリケーションがスムーズかつ効率的に実行されるようにできます。
Original Page: A Guide to Logging and Debugging in Java
IchizokuはSentryと提携し、日本でSentry製品の導入支援、テクニカルサポート、ベストプラクティスの共有を行なっています。Ichizokuが提供するSentryの日本語サイトについてはこちらをご覧ください。またご導入についての相談はこちらのフォームからお気軽にお問い合わせください。