はじめに
自分はお堅いSIer勤めということもあり、外部ライブラリが利用できないことがよくあります。そういう環境で、Javaを使って、ちょっとしたツールなどを作成したいという場合、ロギングにはjava.util.logging(JUL)を利用することになります。
JULの設定方法はいろいろありますが、ちょっとしたツールを作りたいだけなので、ソースコード内で簡単に設定して終わりにしたいです。こういう場合に自分はどうしているのか、というのをここで紹介したいと思います。
設定方法
自分がログにもとめる要件は以下の通りです。
- コンソールとファイルにログを記録する
- ログフォーマットはコンソールとファイルで同じでよいが、SimpleFormatterのデフォルトだとわかりにくいので、わかりやすいものにしたい
- ファイル名はapp_yyyymmdd.logとする (yyyymmddは実行日付)。ログファイルは追記して使う。
これを実現したい場合、mainメソッドの一番最初に、JULの設定処理を記載すればよいです。
public static void main(String[] args) {
Properties properties = new Properties();
properties.setProperty("handlers", "java.util.logging.FileHandler, java.util.logging.ConsoleHandler");
properties.setProperty("java.util.logging.SimpleFormatter.format", "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%1$tL %4$s %2$s %5$s%6$s%n");
properties.setProperty("java.util.logging.FileHandler.pattern", "app_%s.log".formatted(DateTimeFormatter.ofPattern("yyyyMMdd").format(LocalDateTime.now())));
properties.setProperty("java.util.logging.FileHandler.formatter", "java.util.logging.SimpleFormatter");
properties.setProperty("java.util.logging.FileHandler.append", "true");
try {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
properties.store(byteArrayOutputStream, "");
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
LogManager logManager = LogManager.getLogManager();
logManager.reset();
logManager.readConfiguration(byteArrayInputStream);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
// Main Routine
}
やっていることは単純。JULの設定ファイルであるlogging.propertiesファイルに書く内容をソースコード上にハードコードして、ロガーの設定を上書きしているだけです。
使用例
では、実際に利用してみましょう。以下のようなソースコードがあるとします。
public class XXXService {
private static final Logger logger = Logger.getLogger(XXXService.class.getName());
public void run() {
logger.log(Level.INFO, "START");
try {
List<String> lines = Files.readAllLines(Path.of("/not/found/text"));
/// Do Something
} catch (IOException e) {
logger.log(Level.SEVERE, e.getMessage(), e);
throw new UncheckedIOException(e);
}
logger.log(Level.INFO, "END");
}
}
これを実行すると、コンソールとapp_yyyymmdd.logファイルに次のようなログが記録されるはずです。
2023-10-01 12:25:58.585 情報 com.jp.tool.XXXService run START
2023-10-01 12:25:58.653 重大 com.jp.tool.XXXService run \not\found\text
java.nio.file.NoSuchFileException: \not\found\text
at java.base/sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:85)
at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:103)
at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:108)
at java.base/sun.nio.fs.WindowsFileSystemProvider.newByteChannel(WindowsFileSystemProvider.java:236)
at java.base/java.nio.file.Files.newByteChannel(Files.java:380)
at java.base/java.nio.file.Files.newByteChannel(Files.java:432)
at java.base/java.nio.file.spi.FileSystemProvider.newInputStream(FileSystemProvider.java:422)
at java.base/java.nio.file.Files.newInputStream(Files.java:160)
at java.base/java.nio.file.Files.newBufferedReader(Files.java:2922)
at java.base/java.nio.file.Files.readAllLines(Files.java:3412)
at java.base/java.nio.file.Files.readAllLines(Files.java:3453)
at com.jp.tool.XXXService.run(XXXService.java:17)
at com.jp.tool.Main.main(Main.java:35)
環境情報
D:\>javac -version
javac 17.0.3
D:\>java -version
openjdk version "17.0.3" 2022-04-19
OpenJDK Runtime Environment Temurin-17.0.3+7 (build 17.0.3+7)
OpenJDK 64-Bit Server VM Temurin-17.0.3+7 (build 17.0.3+7, mixed mode, sharing)