JavaTM ロギングの概要最終更新日: 2001 年 11 月 26 日 |
ドキュメントの目次 |
1.0 ロギングの概要
1.1 制御フローの概要
1.2 ログレベル
1.3 ロガー
1.4 ロギングメソッド
1.5 ハンドラ
1.6 フォーマッタ
1.7 LogManager
1.8 構成ファイル
1.9 デフォルトの構成
1.10 構成の動的更新
1.11 ネイティブメソッド
1.12 XML DTD
1.13 一意のメッセージ ID
1.14 セキュリティ
1.15 構成管理
1.16 パッケージ化
1.17 地域対応
1.18 リモートアクセスと直列化
2.0 例
2.1 簡単な用法
2.2 構成の変更
2.3 グローバル設定を無視した簡単な用法
2.4 XML の出力例
3.0 付録 A: XMLFormatter 出力用の DTD
ロギング API の詳細は、「J2SE API 仕様」を 参照してください。このドキュメントは、主な要素の概要について説明することを目的としています。
アプリケーションは Logger オブジェクトでロギング呼び出しを行います。ロガーは階層構造を持つ名前空間に編成され、子ロガーは名前空間における親からロギングプロパティの一部を継 承できます。
各ロガーは出力ハンドラのセットを追跡します。デフォルトでは、すべてのロガーが自分の親ロガーに出力を送信します。 より高い階層にあるハンドラは無視するようにロガーを設定することもできます。
Level クラスでは、FINEST (最低の優先順位、値は最小) から SEVERE (最高の優先順位、値は最大) まで 7 つの標準ログレベルが定義されています。
前述のように、クライアントコードは Logger オブジェクトにログ要求を送信します。各ロガーは関係のあるログレベルを追跡し、このレベル以下のログ要求を破棄します。
名前付きロガーのほかに、共有名前空間に表示されない匿名ロガーを作ることもできます。詳細は、1.14 項を参照してください。
各ロガーは、ロギングの名前空間における親ロガーを追跡します。ロガーの親とは、ロギングの名前空間に現存するもっとも近い祖先のことです。ルート ロガーの名前は "" で、ルートロガーに親はありません。すべての匿名ロガーにとって、ルートロガーが親となります。ロガーは、ロガーの名前空間における親からさまざまな属性 を継承できます。特に、次のような属性を継承できます。
ロギングメソッドには 2 種類の書式があり、さまざまなユーザの要求に対応しています。
1 つ目は、明示的なソースクラス名とソースメソッド名を取るメソッドです。このメソッドは、特定のロギングメッセージのソースをすばやくつきとめる必要があ る開発者向けです。次にこの書式の例を示します。
void warning(String sourceClass, String sourceMethod, String msg);
2 つ目は、明示的なソースクラス名とソースメソッド名を取らないメソッドです。これは、簡単なロギングを使用するだけで、詳細なソース情報を必要としない開 発者向けです。
void warning(String msg);
新しいハンドラを開発するのは比較的簡単です。特殊な機能が必要な開発者は、ハンドラをゼロから開発することも、提供 されたハンドラの 1 つをサブクラス化することもできます。
ハンドラと同様に、新しいフォーマッタの開発は比較的簡単です。
静的な LogManager.getLogManager メソッドを使って取得できる単独の LogManager オブジェクトがあります。これは、LogManager の初期化中にシステムプロパティに基づいて作成されます。このプロパティを使うと、コンテナアプリケーション (EJB コンテナなど) は LogManager の独自のサブクラスをデフォルトクラスと置き換えることができます。
ロギング構成は、起動時に読み取られるロギング構成ファイルで初期化することができます。このロギング構成ファイル は、標準の java.util.Properties 形式です。
また、初期化プロパティの読み込みに使用するクラスを指定してロギング構成を初期化することもできます。この機構を使 うと、LDAP や JDBC など、任意のソースから構成データを読み取ることもできます。詳細は、「LogManager API 仕様」を 参照してください。
グローバル構成情報の量はわずかです。これは LogManager クラスの記述に指定されており、起動時にインストールするルートレベルのハンドラのリストが含まれています。
初期構成で名前付きロガーのレベルを指定することもできます。これらのレベルは、その名前付きロガーおよび名前階層でその下にあるすべてのロガーに 適用されます。レベルは、構成ファイルで定義した順に適用されます。
初期構成には、ハンドラやロギングを行うサブシステムが使用する任意のプロパティが含まれます。便宜上、これらのプロパティには、ハンドラクラスの 名前やサブシステムのメインロガー名で始まる名前を使用します。
たとえば、MemoryHandler はプロパティ「java.util.logging.MemoryHandler.size」を使ってリングバッファのデフォルトサイズを決定します。
JRE の出荷時に設定されているデフォルトのロギング構成はデフォルトに過ぎないので、ISV、システム管理者、およびエンドユーザがオーバーライドすることが できます。
デフォルトの構成は、限られたディスク容量だけを利用します。処理できないほど情報量が多くなることはありませんが、 重要な不具合情報は必ず取り込みます。
デフォルトの構成では、ルートロガーのハンドラの 1 つがコンソールへの出力用として設定されます。
ネイティブコードで Java ロギング機構を使う場合は、通常の JNI 呼び出しで Java ロギング API を呼び出す必要があります。
XMLFormatter で使用される XML DTD は付録 A で指定されています。
このDTD では、トップレベルのドキュメントとして「<log>」要素が設計されます。次にそれぞれのログが「<record>」要素とし て記述されます。JVM がクラッシュすると、</log> で XMLFormatter ストリームを正しく閉じてきちんと終了できないことがあります。そのため、ログレコードを分析するツールを用意して、終了していないストリームに対処する 必要があります。
新しいセキュリティアクセス権である LoggingPermission を定義して、ロギングの更新を制御します。
さらに、LogManager には構成ファイルを再読み込みできるメソッドがあります。再読み込みを行うと、構成ファイルの値がプログラムが行なった変更をオーバーライドします。
すべてのロギングクラスは、java.util.logging パッケージにある名前空間の java.* の部分にあります。
各ロガーには、関連付けられたリソースバンドル名があります。対応するリソースバンドルを使って、原文のメッセージ 文字列と地域対応させるメッセージ文字列をマッピングすることができます。
通常、地域対応はフォーマッタが行います。便宜上、フォーマッタクラスは基本的な地域対応と書式化をサポートする formatMessage メソッドを提供します。
RMI で LogRecord オブジェクトを渡すハンドラもあります。したがって、LogRecord クラスは直列化可能です。ただし、LogRecord パラメータをどのように扱うかという問題があります。直列化できないパラメータがある一方で、ロギングに必要とされる以上の状態に直列化するパラメータも あるからです。この問題を回避するため、LogRecord クラスには、Object.toString() でパラメータを文字列に変換してから書き出すカスタムの writeObject メソッドが用意されています。詳細は、「LogRecord API 仕様」を 参照してください。
ほとんどのロギングクラスは、直列化可能にはなっていません。ロガーもハンドラも、特定の仮想マシンに結び付けられたステートフルクラスです。この 点では、どちらも Java.io クラスと似ています。このクラスも直列化できません。
デフォルト設定を使ってロギングを実行する小さなプログラムを次に示します。
package com.wombat;
public class Nose{
// Obtain a suitable logger.
private static Logger logger = Logger.getLogger("com.wombat.nose");
public static void main(String argv[]){
// Log a FINE tracing message
logger.fine("doing stuff");
try{
Wombat.sneeze();
} catch (Error ex){
// Log the error
logger.log(Level.WARNING,"trouble sneezing",ex);
}
logger.fine("done");
}
}
ロギング構成を動的に調整して特定のファイルに出力を送信し、wombat に関する多くの情報を取得する小さなプログラムを次に示します。
public static void main(String[] args){
Handler fh = new FileHandler("%t/wombat.log");
Logger.getLogger("").addHandler(fh);
Logger.getLogger("com.wombat").setLevel("com.wombat",Level.FINEST);
...
}
独自のロギングハンドラを設定し、グローバル設定を無視する小さなプログラムを次に示します。
package com.wombat;
import java.util.logging.*;
public class Nose {
private static Logger logger = Logger.getLogger("com.wombat.nose");
private static FileHandler fh = new FileHandler("mylog.txt");
public static void main(String argv[]) {
// Send logger output to our FileHandler.
logger.addHandler(fh);
// Request that every detail gets logged.
logger.setLevel(Level.ALL);
// Log a simple INFO message.
logger.info("doing stuff");
try {
Wombat.sneeze();
} catch (Error ex) {
logger.log(Level.WARNING, "trouble sneezing", ex);
}
logger.fine("done");
}
}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE log SYSTEM "logger.dtd">
<log>
<record>
<date>2000-08-23 19:21:05</date>
<millis>967083665789</millis>
<sequence>1256</sequence>
<logger>kgh.test.fred</logger>
<level>INFO</level>
<class>kgh.test.XMLTest</class>
<method>writeLog</method>
<thread>10</thread>
<message>Hello world!</message>
</record>
</log>
<!-- DTD used by the java.util.logging.XMLFormatter -->
<!-- This provides an XML formatted log message. -->
<!-- The document type is "log" which consists of a sequence
of record elements -->
<!ELEMENT log (record*)>
<!-- Each logging call is described by a record element. -->
<!ELEMENT record (date, millis, sequence, logger?, level,
class?, method?, thread?, message, key?, catalog?, param*, exception?)>
<!-- Date and time when LogRecord was created in ISO 8601 format -->
<!ELEMENT date (#PCDATA)>
<!-- Time when LogRecord was created in milliseconds since
midnight January 1st, 1970, UTC. -->
<!ELEMENT millis (#PCDATA)>
<!-- Unique sequence number within source VM. -->
<!ELEMENT sequence (#PCDATA)>
<!-- Name of source Logger object. -->
<!ELEMENT logger (#PCDATA)>
<!-- Logging level, may be either one of the constant
names from java.util.logging.Constants (such as "SEVERE"
or "WARNING") or an integer value such as "20". -->
<!ELEMENT level (#PCDATA)>
<!-- Fully qualified name of class that issued
logging call, e.g. "javax.marsupial.Wombat". -->
<!ELEMENT class (#PCDATA)>
<!-- Name of method that issued logging call.
It may be either an unqualified method name such as
"fred" or it may include argument type information
in parenthesis, for example "fred(int,String)". -->
<!ELEMENT method (#PCDATA)>
<!-- Integer thread ID. -->
<!ELEMENT thread (#PCDATA)>
<!-- The message element contains the text string of a log message. -->
<!ELEMENT message (#PCDATA)>
<!-- If the message string was localized, the key element provides
the original localization message key. -->
<!ELEMENT key (#PCDATA)>
<!-- If the message string was localized, the catalog element provides
the logger's localization resource bundle name. -->
<!ELEMENT catalog (#PCDATA)>
<!-- If the message string was localized, each of the param elements
provides the String value (obtained using Object.toString())
of the corresponding LogRecord parameter. -->
<!ELEMENT param (#PCDATA)>
<!-- An exception consists of an optional message string followed
by a series of StackFrames. Exception elements are used
for Java exceptions and other java Throwables. -->
<!ELEMENT exception (message?, frame+)>
<!-- A frame describes one line in a Throwable backtrace. -->
<!ELEMENT frame (class, method, line?)>
<!-- an integer line number within a class's source file. -->
<!ELEMENT line (#PCDATA)>
Copyright ©2002 Sun Microsystems, Inc. All Rights Reserved. |
Java ソフトウェア |