2012年5月8日火曜日

JDK1.4のログ出力を制御するためのlogging.propertiesについてです

標準のlogging.propertiesファイルは、 JDKをインストールしたディレクトリのjre\libの中にあります。
1.まずはlogging.propertiesを覗いてみる
2.ハンドラの指定
3.FileHandlerのプロパティ
4.デフォルトの出力レベル
5.logging.propertiesを指定した実行
6.関連するJava2 SDKドキュメント

1. まずはlogging.propertiesを覗いてみる

JDKをインストールしたディレクトリの中のjre\lib\logging.propertiesを見て下さい。
logging.properties
############################################################  #  	Default Logging Configuration File  #  # You can use a different file by specifying a filename  # with the java.util.logging.config.file system property.    # For example java -Djava.util.logging.config.file=myfile  ############################################################    ############################################################  #  	Global properties  ############################################################    # "handlers" specifies a comma separated list of log Handler   # classes.  These handlers will be installed during VM startup.  # Note that these classes must be on the system classpath.  # By default we only configure a ConsoleHandler, which will only  # show messages at the INFO and above levels.  handlers= java.util.logging.ConsoleHandler    # To also add the FileHandler, use the following line instead.  #handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler    # Default global logging level.  # This specifies which kinds of events are logged across  # all loggers.  For any given facility this global level  # can be overriden by a facility specific level  # Note that the ConsoleHandler also has a separate level  # setting to limit messages printed to the console.  .level= INFO    ############################################################  # Handler specific properties.  # Describes specific configuration info for Handlers.  ############################################################    # default file output is in user's home directory.  java.util.logging.FileHandler.pattern = %h/java%u.log  java.util.logging.FileHandler.limit = 50000  java.util.logging.FileHandler.count = 1  java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter    # Limit the message that are printed on the console to INFO and above.  java.util.logging.ConsoleHandler.level = INFO  java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter      ############################################################  # Facility specific properties.  # Provides extra control for each logger.  ############################################################    # For example, set the com.xyz.foo logger to only log SEVERE  # messages:  com.xyz.foo.level = SEVERE  
おっと、いきなり英語やんけぇ! とのけぞらないで下さい。 これは、Javaのリソースバンドル という形式のファイルで、
  • リソース名 = 値
という規則で記述されています。"#"で始まる行はコメントです。
リソース名の記述が無い行をはずしてみると、
logging.properties
handlers= java.util.logging.ConsoleHandler    #handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler    .level= INFO    java.util.logging.FileHandler.pattern = %h/java%u.log  java.util.logging.FileHandler.limit = 50000  java.util.logging.FileHandler.count = 1  java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter    java.util.logging.ConsoleHandler.level = INFO  java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter  com.xyz.foo.level = SEVERE  
ね、たったこれだけです。順を追って見て行きましょう。

2. ハンドラの指定

ファイルにログを出力するためには前節で見たように java.util.logging.FileHandlerクラスを使います。 このハンドラを指定しているのがhandlersプロパティです。
handler"s"と、複数形になっていることからわかるように、複数のハンドラを指定出来ます。 おあつらえ向きに、FileHandlerがコメントになっている行が見えますよね?
FileHandlerの指定
#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler  
この行のコメントをはずし、ConsoleHandlerだけが指定されている行を逆にコメントにすると、 ファイルにも画面にも出力されるようになります。
FileHandlerとConsoleHandlerの指定
#handlers= java.util.logging.ConsoleHandler  handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler  

3. FileHandlerのプロパティ

ここまで来ればもうだいたいお解りだと思いますが、 ファイルの中の"java.util.logging.FileHandler."で始まる行は、 FileHandlerクラスの動きを決めるためのプロパティです。その部分を見てみましょう。
FileHandlerのプロパティ
java.util.logging.FileHandler.pattern = %h/java%u.log  java.util.logging.FileHandler.limit = 50000  java.util.logging.FileHandler.count = 1  java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter  
  • pattern
    出力ファイル名のパターンを指定します。
    %で始まるのはパターンのメタ文字で、
    • "/" ローカルパス名の区切り文字
    • "%t" システムの一時ディレクトリ
    • "%h" user.home システムプロパティの値
    • "%g" ログのローテーションを識別する生成番号
    • "%u" 重複を解決する一意の番号
    • "%%" 単一のパーセント符号 % に変換
    と規定されています。
    標準のlogging.propertiesでは、
    ユーザのホームディレクトリ配下の"java0.log"
    という名前で出力されることになります。
    (Windows2000の場合は、C:\Documents and Settings\アカウント名\java0.log)
  • limit
    1ファイルに書き込むおおよその最大容量です(単位はバイト)。
  • count
    循環させる出力ファイルの個数です。
  • formatter
    出力書式のフォーマッタです。
    標準ではXMLFormatterが指定されているため出力結果が読みづらいので、SimpleFormatterを指定するほうがいいと思います。
これら以外に、
  • filter
    フィルタクラスを指定します。(デフォルトは指定なし)
  • encoding
    使用する文字セットエンコーディングの名前を指定します。 (デフォルトはプラットフォームのデフォルトエンコーディング)
  • append
    ファイルを追加書き込みモードにする場合はtrueを設定します。 (デフォルトはfalse)
  • level
    出力するログのレベルを指定します。

4. デフォルトの出力レベル

FileHandlerのプロパティにlevelがあるのは説明しましたが、 logging.propertiesファイルをよく見ると次の行が見つかります。
.levelプロパティ
.level= INFO  
これは、全ハンドラ共通の出力レベルを設定するものです。 標準の状態ではこのプロパティによってFileHandlerの出力レベルが決まっているので、 java.util.logging.FileHandler.levelを明示的に指定することでレベルの変更が可能です。
java.util.logging.FileHandler.levelプロパティ
java.util.logging.FileHandler.level = CONFIG  
と指定すると、ファイル出力のログレベルがCONFIG以上になるはずです。
ところが実際にテストをしてみると、FileHandlerクラスの出力レベルの変更は.levelのみによって可能であり、 java.util.logging.FileHandler.levelの指定は全く無視されているようです。(J2SDK 1.4.1_01)
★レベルの詳細に関しては前節を参照して下さい。

5. logging.propertiesを指定した実行

次のようなテストプログラムを準備します。
ytp.test.logging.LoggingPropertiesTesterクラス
package ytp.test.logging;    import java.util.logging.Logger;  import java.util.logging.Level;  import java.lang.reflect.Method;    /**   *  JDK1.4から導入されたログ出力機構をテストするクラスです。   *  単純に画面/ファイルに出力するだけです。   */  public class LoggingPropertiesTester {      /**       *  JDKのロガー(ログ出力クラス)です。       */      private Logger logger = null;            /**       *  デフォルトコンストラクタです。       *  自分のインスタンスをもとにクラス名を取得し、       *  そのクラス名によるLoggerオブジェクトを取得します。       */      public LoggingPropertiesTester() {          logger = Logger.getLogger(this.getClass().getName());      }            /**       *  メインです。       *  LoggerTesterインスタンスを生成し、       *  起動パラメータで指定されたメソッドを呼び出します。       */      public static void main(String[] args) {          LoggingPropertiesTester test = new LoggingPropertiesTester();          try {              // 起動パラメータで指定されたメソッドを呼び出す              Method getter = test.getClass().getMethod(args[0], null);              getter.invoke(test, null);          } catch (Exception e) {              e.printStackTrace();          }      }            /**       *  ログを出力します。       */      public void test1() {          // ログを出力する          this.out(logger);      }            /**       *  例外のスタックトレースを出力します。       */      public void test2() {          try {              makeException();          } catch (NullPointerException e) {              // スタックトレースも出力できます              logger.log(Level.SEVERE, "どうする〜", e);          }      }            private void out(Logger logger) {          logger.log(Level.CONFIG, "デバッグ");          logger.log(Level.INFO, "単なるおまけ");          logger.log(Level.WARNING, "ちょっとまずいんちゃう?");          logger.log(Level.SEVERE, "えらいこっちゃ!!");      }            private void makeException() {          String s = null;          s.toString();      }  }  

プロパティファイルは次のように設定し、名前をloggingtester.propertiesとします。
C:\Source\Java\ytp\test\logging\loggingtester.properties
.level = CONFIG  handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler    java.util.logging.FileHandler.pattern = C:/Source/Java/ytp/test/logging/LoggingTester%u.log  java.util.logging.FileHandler.limit = 50000  java.util.logging.FileHandler.count = 1  java.util.logging.FileHandler.append = true  java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter    java.util.logging.ConsoleHandler.level = SEVERE  java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter  

自作のプロパティファイルをログ出力で使用するためには、 javaコマンドの実行時に-Dオプションを使って、java.util.logging.config.file というシステムプロパティに対してログ出力のリソースファイルを指定します。
loggingtester.propertiesを指定して実行
C:\Source\Java>java -Djava.util.logging.config.file=C:\Source\Java\ytp\test\logg  ing\loggingtester.properties ytp.test.logging.LoggingPropertiesTester test1  2002/11/04 19:53:14 ytp.test.logging.LoggingPropertiesTester out  致命的: えらいこっちゃ!!    C:\Source\Java>  
画面出力に対してはSEVEREを指定しているので 「致命的」エラーしか出力されませんが、ファイルを見てみると、
C:\Source\Java\ytp\test\logging\LoggingTester0.log
2002/11/04 19:53:14 ytp.test.logging.LoggingPropertiesTester out  設定: デバッグ  2002/11/04 19:53:14 ytp.test.logging.LoggingPropertiesTester out  情報: 単なるおまけ  2002/11/04 19:53:14 ytp.test.logging.LoggingPropertiesTester out  警告: ちょっとまずいんちゃう?  2002/11/04 19:53:14 ytp.test.logging.LoggingPropertiesTester out  致命的: えらいこっちゃ!!  
というように全てのログが記録されています。 

続けてtest2を実行してみましょう。
スタックトレースのログ出力(test2の実行)
C:\Source\Java>java -Djava.util.logging.config.file=C:\Source\Java\ytp\test\logg  ing\loggingtester.properties ytp.test.logging.LoggingPropertiesTester test2  2002/11/04 19:56:35 ytp.test.logging.LoggingPropertiesTester test2  致命的: どうする〜  java.lang.NullPointerException          at ytp.test.logging.LoggingPropertiesTester.makeException(LoggingPropert  iesTester.java:71)          at ytp.test.logging.LoggingPropertiesTester.test2(LoggingPropertiesTeste  r.java:55)          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.  java:39)          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces  sorImpl.java:25)          at java.lang.reflect.Method.invoke(Method.java:324)          at ytp.test.logging.LoggingPropertiesTester.main(LoggingPropertiesTester  .java:36)    C:\Source\Java>  
ファイルの中は次の通りです。
C:\Source\Java\ytp\test\logging\LoggingTester0.log
2002/11/04 19:53:14 ytp.test.logging.LoggingPropertiesTester out  設定: デバッグ  2002/11/04 19:53:14 ytp.test.logging.LoggingPropertiesTester out  情報: 単なるおまけ  2002/11/04 19:53:14 ytp.test.logging.LoggingPropertiesTester out  警告: ちょっとまずいんちゃう?  2002/11/04 19:53:14 ytp.test.logging.LoggingPropertiesTester out  致命的: えらいこっちゃ!!  2002/11/04 19:56:35 ytp.test.logging.LoggingPropertiesTester test2  致命的: どうする〜  java.lang.NullPointerException  	at ytp.test.logging.LoggingPropertiesTester.makeException(LoggingPropertiesTester.java:71)  	at ytp.test.logging.LoggingPropertiesTester.test2(LoggingPropertiesTester.java:55)  	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)  	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)  	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)  	at java.lang.reflect.Method.invoke(Method.java:324)  	at ytp.test.logging.LoggingPropertiesTester.main(LoggingPropertiesTester.java:36)

0 件のコメント:

コメントを投稿