SIerだけど技術やりたいブログ

5年目のSIerのブログです

Javaアプリケーションのログ出力

Javaアプリケーションで考慮すべきログはだいたい3パターンに分類できると思う。

標準ロガー系

アプリケーションやライブラリのログで使われる。
ログの実装ライブラリ(java.util.logging, Log4Jなど)と、
それを抽象化するライブラリ(SLF4J, Commons Loggingなど)がある。

いくらでも詳しいサイトがあったので、そちらを参照。
www.bunkei-programmer.net

実現方法

例えばSLF4J + Logback を利用すると、以下のように書ける。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
...
  // SLF4J + Logback
  Logger logger = LoggerFactory.getLogger(Main.class.getName());
  logger.info("Logback logging");

SLF4Jのクラスしか利用していないのに、Lobackの実装が利用される。この実現方法は詳しい説明があったので、そちらを参照。
qiita.com


また、依存ライブラリのログも Logbackで出力できる。外部ライブラリで java.util.logging や Log4J を利用したコードが書かれているにも関わらず、Logbackでログ出力される。なぜか?
f:id:kimulla:20171010125956j:plain

Javaではコンパイル時に依存するクラスファイルをクラスパスに通すが、一度クラスファイルが生成されたら実行時まで依存するクラスファイルは必要ない。
そのため、コンパイル時に利用したクラスファイルとパッケージやメソッドは同一だけど、SLF4Jを利用した実装をしている別のクラスファイルを使うことで、ログ実装を強制的に切り替えている。log4j-over-slf4j や jul-to-slf4j というアダプタ関連のクラスがそれ。
f:id:kimulla:20171010110315j:plain

実際にライブラリの中を見てみるとlog4jのクラスをラップしていることがわかる。
f:id:kimulla:20171010130359p:plain

github.com


※ ただし java.util.logging だけは特別。
java.util.logging は 標準APIのため、クラスファイルがrt.jarに入ってしまっている。
ということは上記のようにjarで実装を差し替えられない。
qiita.com


独自ロガー系

Apache Tomcat の内部ロガーの JULI など。

Apache Tomcat 8 (8.5.23) - Logging in Tomcat

The internal logging for Apache Tomcat uses JULI, a packaged renamed fork of Apache Commons Logging that is hard-coded to use the java.util.logging framework. This ensures that Tomcat's internal logging and any web application logging will remain independent, even if a web application uses Apache Commons Logging.

アクセスログなど、大抵はミドルウェア(APサーバ)ごとにログ出力の設定が必要になる。

標準出力/標準エラー出力

起動・停止のためのbashスクリプトでログを出力するために、標準出力/標準エラー出力をファイルにリダイレクトすることがある。
Apache Tomcatの起動スクリプトの catalina.sh は catalina.out にログを出す。

26-Sep-2017 22:09:52.430 情報 [main] org.apache.catalina.core.StandardService.startInternal サービス [Catalina] を起 動します
26-Sep-2017 22:09:52.430 情報 [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet Engine: Apache Tomcat/8.5.23
26-Sep-2017 22:09:52.450 情報 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Webアプ リケーションディレクトリ [/home/kimura/apache-tomcat-8.5.23/webapps/ROOT] を配備します
26-Sep-2017 22:09:52.887 情報 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/home/kimura/apache-tomcat-8.5.23/webapps/ROOT] has finished in [436] ms
26-Sep-2017 22:09:52.887 情報 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Webアプ リケーションディレクトリ [/home/kimura/apache-tomcat-8.5.23/webapps/docs] を配備します
26-Sep-2017 22:09:52.909 情報 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/home/kimura/apache-tomcat-8.5.23/webapps/docs] has finished in [22] ms
26-Sep-2017 22:09:52.910 情報 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Webアプ リケーションディレクトリ [/home/kimura/apache-tomcat-8.5.23/webapps/examples] を配備します
26-Sep-2017 22:09:53.208 情報 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/home/kimura/apache-tomcat-8.5.23/webapps/examples] has finished in [299] ms
26-Sep-2017 22:09:53.208 情報 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Webアプ リケーションディレクトリ [/home/kimura/apache-tomcat-8.5.23/webapps/host-manager] を配備します
26-Sep-2017 22:09:53.258 情報 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/home/kimura/apache-tomcat-8.5.23/webapps/host-manager] has finished in [50] ms
26-Sep-2017 22:09:53.259 情報 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Webアプ リケーションディレクトリ [/home/kimura/apache-tomcat-8.5.23/webapps/manager] を配備します
26-Sep-2017 22:09:53.287 情報 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/home/kimura/apache-tomcat-8.5.23/webapps/manager] has finished in [28] ms
26-Sep-2017 22:09:53.303 情報 [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]
26-Sep-2017 22:09:53.392 情報 [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-nio-8009"]
26-Sep-2017 22:09:53.394 情報 [main] org.apache.catalina.startup.Catalina.start Server startup in 995 ms


大抵のログ実装で、設定すればアプリケーションログも標準出力に出せる。

またコード中でハンドリングされない例外(OutOfMemoryErrorなど)は標準エラー出力に出る。

public static void main(String[] args) {
    throw new OutOfMemoryError("oome");
}


f:id:kimulla:20171010132955p:plain

最近の流行り

ログをファイルに書き出すのをやめて、stdoutに出す。そしてログ収集基盤などの基盤機能に任せてアプリで管理しない。
12factor.net