(Tomcat Wiki) ロギングのチュートリアル - Logging Tutorial

http://wiki.apache.org/tomcat/Logging_Tutorialの日本語訳。
Wikiは変更が容易な仕組みなのであまり翻訳には向きませんが、読みたかったの訳しました。2009/1/1時点のスナップショット。

訳文

この文書は「無保証」で、つまり明示的にも暗黙的にもいかなる種類の保証も含まずに、提供されていますが、これは商品性の保証や、特定の目的への適合、違反がないことを限定するものではありません。このドキュメントの使用やその他の取扱のようなこのドキュメントとの関係から、関係外で、あるいは、関係内で、契約行為や不法行為等が起こったかどうかにかかわらず、著者はあらゆる要求や損害、その他の不利益についていかなる場合も責任を負いません。

This document is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and non infringement. In no event shall the author be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with this document or the use or other dealings in this document.

java.util.loggingとJULIの入門 - Primer On java.util.logging and JULI

この入門の目的は、チュートリアルの他の部分、特に設定ファイルによるTomcatのログ出力を設定に関連する節の背景となるように、JULIが実装するjava.util.loggingの使い方を説明することです。このセクションを飛ばして、直接設定ファイルの節に進んだ方がよいと考える人もいると思いますが、ここで説明する考え方は設定ファイルを理解するためにも必要です。この節では、例としてプログラムによるログの設定方法を使います。Tomcatの設定ファイルの節では、この節でプログラムによって行うことを、宣言で行う方法について説明します。

The goal of this primer is to demonstrate how to to log with java.util.logging, as implemented by JULI, as a backdrop to the rest of the tutorial, in particular the sections related to configuring Tomcat logging with the configuration file. One may think it's wise to skip this section and proceed directly to the section on the configuration file, but all the concepts talked about here and necessary to understand the configuration file. The examples used in this section show programmatically how logging is configured. The section on Tomcat's configuration file discusses how to accomplish declaratively what is done programmatically in this section.

以下の考え方(クラス)は重要です:

The following concepts (Classes) are important:

  • ログマネージャ
  • ロガー
  • ハンドラ
  • レベル
  • ルートロガー
  • ルートハンドラ
  • LogManager
  • Loggers
  • Handlers
  • Levels
  • Root Logger
  • Root Handler

公式のTomcatのロギングのドキュメントでは、上記の考え方/クラスに大々的に言及してます。

The official Tomcat logging documentation refers to the above concepts / classes extensively.

ロガーの説明を始めましょう。ロガーの目的は何でしょうか?コンソールやファイル、ネットワークなどにログメッセージを書き込むために、開発者はロガーを使います。webアプリケーションのクラスCriticalComponentからjava.util.loggingを使って何らかのログ出力を行いたい場合、まず以下のようなロガーを作ります:

Lets start with Loggers. What's the purpose of a Logger? A Logger is what a developer uses to write a log statements to the console, to a file, to the network, etc. If you wanted to log something from your web application's class CriticalComponent using java.util.logging you would first create a logger like this:


private String nameOfLogger = 'com.example.myapp.CriticalComponent';

or

private String nameOfLogger = CriticalComponent.class.getName();

private static Logger myLogger = Logger.getLogger(nameOfLogger);



ロガーの名前の決め方に注意してください。これはTomcatのロギングの設定を説明するための重要な点です。なぜmyLoggerがstaticフィールドなのかを考えたいのではないでしょうか(ヒント myLoggerはCriticalComponentのすべてのインスタンスで共有されます)。

Pay attention to how we defined the name of the Logger. This is important to the material explaining Tomcat's logging configuration. You may also want to think about why the myLogger is a static field (Hint myLogger is shared among all instances of CriticalComponent).

今、CriticalComponentクラスでログメッセージを作るためのロガーがあります。ここで、例えば、以下をするとします:

Now you have a logger to create logging messages from your class CriticalComponent. For example you could now try something like this:

public void wasssup() {

myLogger.info("Ah Yeah Baby - that's the end of System.out.println");

}

webアプリケーションをデプロイしてこのコードを実行すると、コンソール上かcatalina.out中にこのメッセージが現れます。

If you ran this code with a deployed web application you would see this statement on the console or in catalina.out:


INFO; 322125105255ms; 4407662;# 1; com.example.myapp.CriticalComponent; wasssup; Ah Yeah Baby - that's the end of System.out.println



ロガーの名前、および、メッセージを出力したメソッドの名前の両方がログメッセージ内に現れているのがわかります。これは、ロガーの設定を変更したい場合に重要です。たとえば、不要なログの出力をやめたい場合です。

Notice that both the name of the Logger and the method that logged the message are mentioned in the log statement. This is important to know when you want to alter the configuration of the Logger. For example you might want to turn this logger off, because it's not that useful.

ファイルにもコンソールにも出力したい場合はどうでしょうか?そのためには二つのハンドラを定義する必要があります。二つ作るには以下ようにします:

What if you wanted the output to appear in a file and on the console? For that you need to define 2 Handlers. Create the two like this:


Handler fileHandler = new FileHandler("/var/log/tomcat/myapp.log");

Handler consoleHandler = new ConsoleHandler();

myLogger.addHandler(fileHandler);

myLogger.addHandler(consoleHandler);



myLoggerはコンソールとファイル/var/log/tomcat/myapp.logの両方にログ出力するようになります。

Now myLogger will log to both the console and the file /var/log/tomcat/myapp.log.

ここまででLoggerとHandlerについてわかりましたが、レベルやルートロガー、ルートハンドラについてまだ触れていません。これらはどのようなものでしょうか?

So now we understand Loggers and Handlers, but we have not touched on Levels, Root Loggers, and Root Handlers yet. What are those?

ルートロガーの説明を始めましょう。ルートロガーは「」という名前を持つロガーです。この目的はなんでしょうか?このようなmyLoggerでログ出力するとしましょう:

Lets start with a root Logger. A root logger is a logger whose name is "". What's the purpose of it? Suppose you tried to do some logging with myLogger like this:


myLogger.finest("Sooooo Fine");



この文が呼ばれてもログには何も現れません。どうなっているのでしょうか?JULIのルートロガーのレベルがデフォルトでINFOであるというのが、答えです。INFOレベルは対応する整数値3が割り当てられています。myLoggerはログ出力時に、まずレベルをチェックします。myLoggerのレベルがログ出力メソッド(finest)の固有のレベルより大きければ、レコードがログ出力されます。この例ではfinestはレベル0に対応します。0は3より小さいので、ロガーはメッセージをログ出力しません。myLoggerは3委譲のレベルのログメッセージだけをログ出力します。よって、たとえば

And nothing shows up in your log, but you know that this statement is being called. What's going on? The answer is that the JULI root logger's Level is set to INFO by default. The level INFO has a corresponding integer assigned to it, which is 3. When myLogger attempts to log it first checks its level. If myLogger's level is greater than the level intrinsic to the method doing the logging (finest), then the record will be logged. In this case the logging method finest corresponds to Level zero. Zero is less than 3, hence the logger does not log the message. My logger will only log messages with a level that is greater than or equal to 3. So for instance if


myLogger.severe("Oohhh %#$@#$!!!")



が呼ばれた場合、severeメソッドの固有のレベルは3より大きいのでログ出力されます。ここまでわかると、明示的に設定していなののに、どうしてmyLoggerのレベルが3(INFO)なのか気になると思います。ルートロガーから来ているというのが、答えです。今、「com.example.myapp」という名前のロガーを作ってレベルを設定するとします。myLoggerのレベルはルートロガーのレベルのままでしょうか。違います。なぜなら、「com.example.myapp」というロガーがmyLoggerの親ロガーであり、myLoggerのレベルがは代わりに親ロガーのレベルと同じになるからです。なぜ「m.example.myapp」ロガーが親になるのでしょうか?名前が「com.example.myapp」だからです。「org.charity.generous」という名前であれば、親ロガーになりません。パターンがわかるでしょうか(myLoggerの名前には「com.example.myapp」が含まれる)?

is called, it will get logged because the level intrinsic to the method severe is greater than 3. So you are following this, but wondering how myLogger's level got set to 3 (INFO), since we never explicitly set it. The answer is that it comes the root Logger. Now suppose you created logger named 'com.example.myapp' and set its level. Would myLogger still get its level from the root Logger. It would not. The reason is that the logger named 'com.example.myapp' is now a parent logger to myLogger, and myLogger gets its level from it instead. How did the 'com.example.myapp' Logger become a parent? It's because of its name 'com.example.myapp'. If it were named 'org.charity.generous', it would not be a parent logger. Do you see the pattern (myLogger includes 'com.example.myapp' in its name)?

これをよく考えたので、レベルが何であるかがわかったでしょう。レベルによって何がログ出力されるかが決まります。以下のようにmyLoggerに直接レベルを設定することもできます:

Now that we mulled that over you have an idea of what a level is as well. The Level determines what gets logged. You can set the level directly on myLogger like this:

myLogger.setLevel(Level.WARNING);

この場合、myLoggerはWARNINGかSEVEREのレベルのメッセージだけを出力します。

In this case only messages with a level of WARNING or SEVERE will get logged by myLogger.

myLoggerによって出力されたログは、myLoggerのハンドラに渡されます。しかし、myLoggerにハンドラを割り当ていない場合どうなるのでしょうか。ハンドラはどうやって取得するのでしょう?

Now remember that once something gets logged by myLogger, it's handed over to myLogger's Handlers. But what if we never assigned any Handlers to myLogger. How would it get its Handler?

ルートハンドラが答えです。ルートロガーはルートハンドラを持っています。そこで、myLoggerにハンドラを明示的に指定しない場合、ルートロガーに指定されたハンドラを使います。もし、myLoggerにではなく「com.example.myapp」という名前のロガーにハンドラを指定すれば、myLoggerは、ルートロガーの指定されたハンドラの代わりに「com.example.myapp」に指定されたハンドラを使います。

The answer is the root Handlers. The root logger has root Handlers. So if you don't explicitly define any Handlers for myLogger, it will use the Handlers attached to the root Logger. Now if you did attach Handler(s) to the logger named 'com.example.myapp', but not to myLogger, then myLogger would use the Handler(s) attached to 'com.example.myapp', instead of the Handlers attached to the root Logger. In other words myLogger uses the Handlers of the closest Logger ancestor, which in this case is either the 'com.example.myapp' Logger or the root Logger.

JULIを使ったTomcatの設定のために、以上をすべて理解することが重要です。

So all of the above is important to understand in order to be able to configure Tomcat logging with JULI. Now we can talk about doing so via the configuration file.

TomcatのJULIの設定する - Configuring Tomcat JULI

ロガーを設定する - Configuring Loggers

myLoggerの設定を、ここまでのようにプログラムによってではなく、logging.propertiesで行いたいものとし、レベルをSEVEREに設定します。以下を設定ファイルに追加します:

Suppose we wanted to configure myLogger via a logging.properties file, rather than programmatically as we did earlier, and simply set its Level to SEVERE. We would put the following in the configuration file:


com.example.myapp.CriticalComponent.level = SEVERE



これがロガーの設定方法です。ここでは、ロガーの名前、ピリオド、そして、設定したいプロパティの名前「レベル」を続けて指定しています。ロガーのクラスが複数ある場合、それぞれのクラスに個別にロギングレベルを設定しなくても、以下のようにルートロガーにロギングレベルを設定することができます。

That's how Loggers are configured. We specified the name of the Logger followed by followed by a period followed by the name of the property we wanted to set, which is 'level' in this case. If we had several classes with corresponding loggers, and we did not want to set the logging level for each class individually, we could set the logging level on the root Logger like this:


.level = SEVERE



これで、(プログラムか設定のどちらかで)ログレベルがデフォルト以外に設定されたロガーを除いて、すべてのロガーのレベルがSEVEREになります。

This will set the level on all loggers to SEVERE, unless the Logger uses a non-default level (Either programmatically or via configuration).

すべてのロギングをオフにしたい場合、以下のように単純にルートロガーを設定し、この設定を上書く子ロガーがないようにします:

So if you wished to turn logging off all together simply configure the root logger like this and make sure that there are no child loggers that override this setting:


.level = OFF



逆に、すべてをログ出力するには以下のようにします:

On the flip side to log everything set it like this:


.level = ALL


ハンドラを設定する - Configuring Handlers

「com.example.myapp.CriticalComponent」というロガーにハンドラを追加したいとします。

Suppose that we also wanted to add a Handler to the Logger named com.example.myapp.CriticalComponent.

以下のようにハンドラを設定します:

We could define our handler like this:

handlers = org.apache.juli.FileHandler

加えて以下のように設定できます:

And configure it like this:

org.apache.juli.FileHandler.level = WARNING
org.apache.juli.FileHandler.directory = /var/log/tomcat/
org.apache.juli.FileHandler.prefix = mywebapp