導入の手間がないのに利用者が少なすぎる感のある java.util.logging の簡単な使い方を紹介します。
みんな簡単な使い方ができることを知らないから使わないんじゃないかな?
簡単な使い方
1. ログを記録するクラスを実装する
import java.util.logging.*;
public class Main {
private static final Logger log = Logger.getLogger(Main.class.getName());
public static void main(String[] args) {
log.severe("重大メッセージ");
log.warning("警告メッセージ");
log.info("情報メッセージ");
log.config("構成メッセージ");
log.fine("「普通」メッセージ");
log.finer("詳細メッセージ");
log.finest("最も詳細なメッセージ");
}
}
Lombok を使って private static final Logger log = Logger.getLogger(Main.class.getName()); と書くかわりに @Log を使うこともできます。
2. logging.properties を用意する
カレント ディレクトリーに以下の内容で保存します。
handlers=java.util.logging.FileHandler,java.util.logging.ConsoleHandler
.level=ALL
java.util.logging.FileHandler.level=ALL
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.FileHandler.pattern=main.log
java.util.logging.FileHandler.append=true
java.util.logging.ConsoleHandler.level=INFO
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.SimpleFormatter.format=%1$tF %1$tT.%1$tL %4$s %2$s - %5$s%6$s%n
3. -Djava.util.logging.config.file=logging.properties を付けて実行する
$ java -Djava.util.logging.config.file=logging.properties Main
IntelliJ の場合、Run > Edit Configurations... のダイアログで、Modify options のメニューから Add VM Options を選んで入力する必要があります。
4. ログが出力される
標準エラー出力に INFO までのログ、main.log に全てのログが記録されます。
2025-07-01 19:48:39.696 重大 Main main - 重大メッセージ
2025-07-01 19:48:39.737 警告 Main main - 警告メッセージ
2025-07-01 19:48:39.738 情報 Main main - 情報メッセージ
2025-07-01 19:48:39.738 構成 Main main - 構成メッセージ
2025-07-01 19:48:39.738 普通 Main main - 「普通」メッセージ
2025-07-01 19:48:39.739 詳細 Main main - 詳細メッセージ
2025-07-01 19:48:39.740 最も詳細 Main main - 最も詳細なメッセージ
以上、簡単な使い方でした。
以下解説ですが、ごめんなさい、使うのは簡単でも、解説は難しいです。
logging.properties 解説
デフォルトと、上で使用した logging.properties の内容を解説します。
デフォルトの logging.properties
上記のように指定しない場合、デフォルトでは $JAVA_HOME/conf/logging.properties が使われます。これは以下のような内容です。(デフォルトが指定されているものも含め、効いている行だけ抜き出しました。)
handlers= java.util.logging.ConsoleHandler
.level= INFO
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
- ハンドラーとして標準エラー出力に出力する ConsoleHandler のみが指定されています
- ルート Logger (
""という名前の Logger)1 の.levelが INFO であり、INFO 以上の重大さのもののみが処理対象となります - ルート Logger の処理対象のうち、java.util.logging.ConsoleHandler.level に指定された INFO 以上の重大さのものが標準エラー出力に出力されます
- ConsoleHandler の formatter は SimpleFormatter です
- SimpleFormatter の format は指定されていないので、実装固有のデフォルトのフォーマットが使われます2
- 手元の OpenJDK 21 (Temurin) では以下のような癖のある形式です
7月 01, 2025 8:08:08 午後 Main main 重大: 重大メッセージ
- 手元の OpenJDK 21 (Temurin) では以下のような癖のある形式です
-
handlers= java.util.logging.ConsoleHandler以外はデフォルト値なので記述不要です
上で記述した logging.properties
再掲します。
handlers=java.util.logging.FileHandler,java.util.logging.ConsoleHandler
.level=ALL
java.util.logging.FileHandler.level=ALL
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.FileHandler.pattern=main.log
java.util.logging.FileHandler.append=true
java.util.logging.ConsoleHandler.level=INFO
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.SimpleFormatter.format=%1$tF %1$tT.%1$tL %4$s %2$s - %5$s%6$s%n
出力例も再掲します。
2025-07-01 20:48:13.986 最も詳細 Main main - 最も詳細なメッセージ
- ハンドラーとして ConsoleHandler に加えて、ファイルに出力する FileHandler を指定しています
- ルート Logger のレベルに ALL を指定して、すべてを処理の対象にしています
- 注意: 性能改善のために
log.finest(() -> some.superHeavyToString())のようにラムダ式を使って書かれているものもすべて実行されます
- 注意: 性能改善のために
- ログ ファイルにすべて出力するように、
java.util.logging.FileHandler.level=ALLを指定しています - ログ ファイルに記録する際のフォーマッターをコンソールと同じ SimpleFormatter にしています
- デフォルトは XMLFormatter です3
- 出力先を main.log にしています
- ここで指定できるパターンは FileHandler の JavaDoc を参照してください
- 実行のたびにログ ファイルを上書きするのではなく、追記 (append) するようにしています
- ConsoleHandler の設定はデフォルトと同じです
- SimpleFormatter のフォーマットを指定して、改行なしでわかりやすく表示するようにしています
-
%1$は date (ZonedDateTime) で、tF、tT、tLなどと日付および時刻表現に使用する型の書式指示子を駆使して自然な表記に変換しています -
%2$は source で、呼び出し元になります -
%3$は logger ですが Main.java でクラス名をロガー名にしていて、%2$にすでにクラス名が含まれているので使っていません -
%4$は level です -
%5$は messsage です -
%6$は thrown で、Logger#throwing などを使った際に改行を含むスタックトレースになります2025-07-01 20:48:13.986 詳細 Main main - THROW java.lang.Exception: error message at Main.main(Main.java:14) - 詳細は SimpleFormatter#format をご覧ください
- 書式文字列の詳細も合わせてご覧ください
-
- CondoleHandler、FileHandler に指定可能なものについて、詳細は JavaDoc をご覧ください
わかりやすさを優先してファイルにも SimpleFormatter を使いましたが、SimpleFormatter はスレッドの情報などが出ないので、監視ツールなどが XML に対応している場合は XMLFormatter を使うのが良いかもしれません。
ログ レベルについて
重大なものから順に、以下のレベルが使えます。(ハンドラーには ALL、NONE も設定できます。)
| レベル |
|---|
| SEVERE |
| WARNING |
| INFO |
| CONFIG |
| FINE |
| FINER |
| FINEST |
INFO 以下はどのレベルでログを出力するか迷うところです。日本語では FINE が「普通」となっていますが、英語の意味からするとこれは「詳細」が適切で、普通は使うべきでないと思います。とはいえ、日本語ロケールで自然に見えるように出力するというのも一つの考え方です。
ルート ロガーと標準エラー出力を使う ConsoleHandler がデフォルトで INFO、FileHandler がデフォルトで ALL となっていますので、デフォルトで画面に出したほうが良いメッセージは INFO 以上にするというのも一つの考え方です。
また、throwing、entering、exiting はいずれも FINER となっており、これも使うレベルを考える上で参考になります。
以上から、個人的には以下のようにするのが良さそうに思いました。
- 普段から表示したいものは INFO
- 普段は表示するほどではない設定情報は CONFIG
- トラブル時の切り分けに使えそうな情報は FINE
- デバッグ用のログは FINER
- デバッグ時の邪魔になるようなログは FINEST
参考
- パッケージjava.util.logging
- 8 Javaロギングの概要
- Java Util Logging Configuration: A Practical Guide for DevOps & SREs