Jakarta-Commons-Logging の概要

logging.png

Jakarta-Commons-Logging のアプリ側プログラミング

  1. 環境
    1. Jakartaプロジェクトのダウンロードサイトから、commons-logging-1.0.4.zipをダウンロード
    2. 展開してできたjarファイルをプロジェクトのクラスパスに通す
      1. commons-logging.jar
      2. commons-logging-api.jar
  2. プログラミング
    1. loggerのインスタンス
      1. logger=LogFactory?.getLog( 自Class ) で取得。ログに出力するClass名になったり、出力するレベルをパッケージによって変えるのに使う。
      2. クラスのstaticフィールドとして保持する
    2. log出力
      1. 対応するメソッドを使うことにより重要度を変えることができる
      2. 第二引数にthrowableをとることができる(通常ログファイルにはスタックトレースが出力される...FormatterなりLayoutの設定次第ですが)
    3. 重いログ出力の前には、logger.is${Level}Enable() メソッドで、現在の設定上出力しなければならないログかを調べること
      記述例:
       public class LogSample {
       
        /** jakarta-commons-logging */
        private static Log logger = LogFactory.getLog(LogSample.class);
       
        public static void main(String[] args) {
       
          try {
       
            /* ----- 基本的なログ出力 ------ */
            logger.fatal("本当にやばいログ");
            logger.error("普通にやばいログ");
            logger.warn("ちょっとやばいログ");
            logger.info("運用時に必要なログ");
            logger.debug("開発時に必要なログ");
            logger.trace("デスマ時に必要なログ");
            /* ---------------------------- */
            
            throw new NullPointerException("('A`) ぬるぽ ");
          } catch (Exception ex) {
       
            /* -- 例外情報を含んだログ出力 -- */
            logger.fatal("本当にやばいログ", ex);
            logger.error("普通にやばいログ", ex);
            logger.warn("ちょっとやばいログ", ex);
            logger.info("運用時に必要なログ", ex);
            logger.debug("開発時に必要なログ", ex);
            logger.trace("デスマ時に必要なログ", ex);
            /* ---------------------------- */
          }
       
          /* ------- 重いログ出力 -------- */
          java.util.Map m = new HashMap();
       
          if (logger.isDebugEnabled()) {
            // Debugレベルが有効ならば、Mapの中身をすべてログに出力する
            Set keys = m.keySet();
            for (Iterator it = keys.iterator(); it.hasNext();) {
              Object key = it.next();
              logger.debug(key + "=" + m.get(key));
            }
          }
          /* ---------------------------- */
        }
       }
      

java.util.loggingの設定

  1. 設定ファイル
    1. %JAVA_HOME%\jre\lib\logging.properties
    2. あるいはjava vm起動時に、-Djava.util.logging.config.file=設定ファイル名 で指定
       
  2. 設定方法
    1. ログレベルの対応
      java.util.loggingCommons-Logging
      SEVERElogging.fatal(),logging.error()
      WARNINGlogging.warn()
      INFOlogging.info()
      CONFIG
      FINElogging.debug()
      FINER
      FINESTlogging.trace()
       
    2. あとは、%JAVA_HOME%\jre\lib\logging.propertiesを見りゃあ分かりますな。できることは、コメントに書いてあることで全部です。
      %JAVA_HOME%\jre\lib\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            <-- 最大ファイル長さ(byte)
       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 
       # <-- com.xyz.foo パッケージ以下はSEVERE以上のログのみを出力するようにする。
      

log4jの設定

  1. 環境
    1. Logging Services Project @ Apache のダウンロードサイトから logging-log4j-1.2.9.zip をダウンロード
    2. 展開してできたjarファイルをプロジェクトのクラスパスに通す
      1. log4j-1.2.9.jar
    3. 設定ファイルのlog4j.xmlをクラスパスのルートに置く
      1. eclipseなら、\srcにおいておくと、ビルド時に \binにコピーしてくれます
      2. antの場合は、コピーするようにスクリプトを書かなければなりませんね
  2. 設定方法
    1. ログレベルの対応
      log4jCommons-Logging
      FATALlogging.fatal()
      ERRORlogging.error()
      WARNlogging.warn()
      INFOlogging.info()
      DEBUGlogging.debug(),logging.trace()
       
    2. log4j.xmlの構造
      1. log4j.xmlは、appender・category・rootから成ります
        <log4j:configuration> ::= <appender>+ <category>* <root>
      2. appenderセクションには、ログ出力クラスの設定を行います。appenderセクションはlayoutセクションを含み、layoutセクションでログの整形に関する設定を行います。
        <appender> ::= 使用Appenderクラス名 Appenderデフォルトログレベル 出力設定 <layout>?
        <layout>   ::= 使用Layoutクラス名 書式
      3. rootセクションでは、デフォルトのログレベルと、使用するAppender名を指定します。出力されるログレベルは、appenderセクションで定義されたデフォルトログレベルとrootセクションで定義されたデフォルトログレベルの内重要度が大きいものが使用されます。
        <root>     ::= Rootデフォルトログレベル 使用Appender名+
      4. categoryセクションでは、特定のカテゴリ(パッケージ)に対して、ログレベルを変更することができます(rootではinfoレベルだが、com.xx.buggy.* だけは traceレベル で出力したい・・・など)。必ずrootカテゴリよりも前に定義します。
        <category> ::= 適用カテゴリ名 ログレベル 使用Appender名+
    3. 記述例
       <?xml version="1.0" encoding="UTF-8" ?>
       <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
       
       <log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
       
      	<!-- ********************** レイアウト書式 ***********************
      		%r アプリ起動から何ミリ秒たったか
      		%d 日時 %d{dd MMM yyyy HH:mm:ss.SSS}
      		
      		%t スレッド名
      		%x ネスト化診断コンテキスト(@see org.apache.log4j.NDC)
      		%X マップ化診断コンテキスト(@see org.apache.log4j.MDC)
      		
      		%p レベル名(FATAL/ERROR/WARN/INFO/DEBUG)
      		%c カテゴリー名(クラス名) // LogFactoryで指定したもの 
      		
      		%m メッセージ
      		
      		%n 改行コード
      		%% %
      		
      		%10m     桁数が10桁未満のとき、左側にSPを追加して10桁にする
      		%.10m    桁数が10桁以上のとき、11桁目以降を削除して10桁にする
      		%10.20m  (左側にSPを足して)桁数を10桁〜20桁にそろえる
      		%-10m    桁数が10桁未満のとき、右側にSPを追加して10桁にする
      		%-10.20m (右側にSPを足して)桁数を10桁〜20桁にそろえる
      		
      		※パフォーマンス上の問題があるので避けるべき書式(StatcTraceから取得?)
      		
      		%C クラス名
      		%M メソッド名
      		%l ファイル名・行番号
      		%F ファイル名
      		%L 行番号
      	-->
      		
      	<!-- ********************** 標準出力への出力 ********************** -->
      	<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
      	
      		<!-- デフォルトのログレベル -->
      		<param name="threshold" value="debug" />
      		
      		<!-- レイアウトの指定 -->
      		<layout class="org.apache.log4j.PatternLayout">
      			<param name="ConversionPattern"
      			       value="[%-5p] %.30m%n" />
      		</layout>
      	</appender>
      	
      	<!-- ********************** ファイルへの出力 ********************** -->
      	<appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
      	
      		<!-- デフォルトのログレベル -->
      		<param name="threshold" value="info" />
      		
      		<!-- ファイル情報 -->
      		<param name="file" value="log.txt" />
      		<param name="append" value="false" />
      		<param name="datePattern" value="'.'yyyy-MM-dd" />
      		<!--
      			ファイルローテートの指定
      			'.'yyyy       年の変わり目(1月1日の0時)
      			'.'yyyy-MM    月の変わり目(1日の0時)
      			'.'yyyy-ww    週の変わり目(日曜の0時)
      			'.'yyyy-MM-dd 日の変わり目(0時)
      		-->
      		
      		<!-- レイアウトの指定 -->
      		<layout class="org.apache.log4j.PatternLayout">
      			<param name="ConversionPattern"
      			       value="%d{yyyy-MM-dd HH:mm:ss.SSS} %x [%-5p] %m%n" />
      		</layout>
      	</appender>
       
      	<!-- ********************** syslogdへの出力 ********************** -->
      	<appender name="SYSLOG" class="org.apache.log4j.net.SyslogAppender">
      	
      		<!-- デフォルトのログレベル -->
      		<param name="threshold" value="error" />
      		<!--
      			(log4j)  (syslog)
      			FATAL    crit,panic,emerg
      			ERROR    err,error 
      			WARN     warning,warn 
      			INFO     info 
      			DEBUG    debug 
      		-->
      		
      		<!-- syslogサーバ情報 -->
      		<param name="SyslogHost" value="localhost" />
      		<param name="facility" value="user" />
      		<!--
      			facility には以下の項目を設定できる
      			kern , user , mail , daemon , auth(認証) , syslog , lpr ,
      			news , uucp , cron , authpriv(アプリ固有の認証) , ftp , local0〜7
      		-->
       
      		<!-- レイアウトの指定 -->
      		<layout class="org.apache.log4j.PatternLayout">
      			<param name="ConversionPattern"
      			       value="%d{MMM dd HH:mm:ss} [%-5p] %.30m%n" />
      		</layout>
      	</appender>
       
      	<!-- ********************** NTEventへの出力 ********************** -->
      	<!-- NTEventを記録するサーバの C:\WINNT\SYSTEM32 に
      	     logging-log4j-x.x.x\src\java\org\apache\log4j\nt\NTEventLogAppender.dll
      	     をコピー
      	-->
      	<appender name="NTEvent" class="org.apache.log4j.nt.NTEventLogAppender">
      	
      		<!-- デフォルトのログレベル -->
      		<param name="threshold" value="fatal" />
      		
      		<!-- NTEventサーバの設定 -->
      		<param name="source" value="XXアプリ" />
      		
      		<!-- レイアウトの指定 -->
      		<layout class="org.apache.log4j.PatternLayout">
      			<param name="ConversionPattern"
      			       value="%d{HH:mm:ss.SSS} [%-5p] %.30m%n" />
      		</layout>
      	</appender>
       
      	<!-- ********************** SMTPへの出力 ************************* -->
      	<!-- JavaMail(mail.jar)  http://java.sun.com/j2ee/ja/javamail/index.html
      	     JAF(activation.jar) http://java.sun.com/beans/glasgow/jaf.html
      	     をクラスパスに通しておく
      	-->
      	<appender name="SMTP" class="org.apache.log4j.net.SMTPAppender">
      	
      		<!-- デフォルトのログレベル -->
      		<param name="threshold" value="fatal" />
      		
      		<!-- メール送信の設定 -->
      		<param name="SMTPHost" value="mail.xxxxxxx.com" />
      		<param name="To" value="xxxxx@xxxxxxx.com" />
      		<param name="Subject" value="【緊急】XXアプリ致命的エラーの発生" />
      		<param name="From" value="XXMaster@xxxxxxxxxx.com" />
      		<param name="BufferSize" value="1" />
      		
      		<!-- レイアウトの指定 -->
      		<!-- PatternLayoutは、getContentType()の返値に文字コードを指定できない
      		     ので、文字コード を指定して text/plane; chaset=XXX を出力できるよう
      		     に拡張したEncordablePatternLayoutを独自に作る
      		     (http://issues.apache.org/bugzilla/show_bug.cgi?id=32074 で議論中)
      		-->
      		<layout class="EncodablePatternLayout">
      			<param name="Charset" value="ISO-2022-JP" />
      			<param name="ConversionPattern"
      			       value="%d{HH:mm:ss.SSS} [%-5p] %.30m%n" />
      		</layout>
      	</appender>
       
      	<!-- **************** Socket(Log4JMonitor)への出力 *************** -->
      	<!-- http://freshmeat.net/projects/log4jmonitor/?topic_id=45%2C846%2C47 -->
      	<!-- log4jmonitor-1.1.jar をダブルクリックすると起動します                -->
      	<appender name="SOCKET" class="org.apache.log4j.net.SocketAppender">
      	
      		<!-- デフォルトのログレベル -->
      		<param name="threshold" value="debug" />
      		
      		<!-- 送信先の設定 -->
      		<param name="RemoteHost" value="localhost" />
      		<param name="Port"       value="27272" />
      		
      		<!-- layoutは指定しない -->
      	</appender>
      	
      	<!-- ********************** category定義 ************************* -->
      	<logger name="com.xx.buggy" additivity="false"> <!-- root および他の category の設定を引き継がない -->
      		<level value="debug" />
      		<appender-ref ref="STDOUT" />
      	</logger>
      	
      	<!-- ********************** root定義 ***************************** -->
      	<root>
      		<priority value="info" />
      		<appender-ref ref="STDOUT" />
      		<appender-ref ref="SOCKET" />
      	</root>
      	 
       </log4j:configuration>
      
  3. SMTPAppenderで日本語のメールを送る
    PatternLayout?.getContentType?()が常に、"text/plain"を返すので、日本語のメールを送ることができません。
    そこで、PatternLayout?を拡張して、ContentType?を指定できるEncordablePatternLayout?を作りました。
     EncodablePatternLayout.java:
     
     import org.apache.log4j.PatternLayout;
     
     public class EncodablePatternLayout extends PatternLayout {
     
      private String charset;
     
      public void setCharset(String charset) {
        this.charset = charset;
      }
     
      public String getContentType() {
        return "text/plain; charset=\"" + charset + "\"";
      }
     }
    
    log4j.xml(抜粋):
    
    <layout class="EncodablePatternLayout">
      <param name="Charset" value="ISO-2022-JP" />
      <param name="ConversionPattern"
             value="%d{HH:mm:ss.SSS} [%-5p] %.30m%n" />
    </layout>
  4. ネスト化診断コンテキスト
    • ThreadLocal? な NDC に対して、push(String)で文字列を指定できる
      • App.java
        package com.mycompany.log4jexam;
         
        import org.apache.commons.logging.Log;
        import org.apache.commons.logging.LogFactory;
        // import org.apache.log4j.Logger;
        import org.apache.log4j.NDC;
          
        public class App {
            /**
             * commons-logging
             * commons-logging から log4j を使った場合でも NDC が参照される
             */
            private static final Log logger = LogFactory.getLog(App.class);
        
            // log4j Logger
            // private static final Logger logger = Logger.getLogger(App.class);
            
            public static void main(String[] args) {
                NDC.push("1st");
                logger.debug("Message-A");
                NDC.push("2nd");
                logger.debug("Message-B");
                NDC.push("3rd");
                logger.debug("Message-C");
                NDC.remove();
                logger.debug("Message-D");
            }
        }
        
      • log4j.xml
        <?xml version="1.0" encoding="UTF-8" ?>
        <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
        <log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
        
        	<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
        	
        		<!-- デフォルトのログレベル -->
        		<param name="threshold" value="debug" />
        		
        		<!-- レイアウトの指定 -->
        		<layout class="org.apache.log4j.PatternLayout">
        			<param name="ConversionPattern"
        			       value="%d{HH:mm:ss.SSS} [%-5p] %x %m%n" />
        		</layout>
        	</appender>
        		
        	<root>
        		<priority value="debug" />
        		<appender-ref ref="STDOUT" />
        	</root>
        	 
        </log4j:configuration>
        
    • 出力結果
      11:00:51.717 [DEBUG] 1st Message-A
      11:00:51.717 [DEBUG] 1st 2nd Message-B
      11:00:51.717 [DEBUG] 1st 2nd 3rd Message-C
      11:00:51.717 [DEBUG]  Message-D
    • ServletのフィルタやEJBのFacadeで、接続ユーザ名やマシン名を NDC に入れておけば、そのトランザクション内のログに共通的に NDC にいれた文言を出力できる
    • 注:) NDC は ThreadLocal? なので Thread を再利用する場合 (Thread Pool を使う場合) には、必ず NDC.remove() で NDC を空にする必要がある
    • スタックではなく、マップの MDC もある。たいていログに出力する文言は最初から決まっているので、そこまで柔軟にしなくてもいいかな (柔軟にいろいろな状況に対応できると言うことは、その分運用が複雑になる)

参考文献

  1. Jakarta-Commons-Logging
    1. Jakartaプロジェクト commons-logging
    2. Jakartaプロジェクト JavaDoc
    3. 岡本隆史・吉田英嗣・山田卓也・樋山大輔, 2003, Javaオープンソース徹底攻略, ソフト・リサーチ・センター,247-252 pp.
  2. java.util.logging
    1. Sun JavaTM ロギングの概要
    2. Sun J2SE JavaDoc(java.util.loggingパッケージ)
    3. 田中宏和, 2003, まるかじりJava, 毎日コミュニケーションズ
  3. log4j
    1. Apacheプロジェクト Logging Services Project @ Apache
    2. 岡本隆史・吉田英嗣・山田卓也・樋山大輔, 2003, Javaオープンソース徹底攻略, ソフト・リサーチ・センター,252-263 pp.
    3. TECHSCOPE Java
    4. freshmeat.net Log4jMonitor
    5. LayoutのContentType?に関する問題 apache-logging bugzilla
    6. log4rss-log4jのログ出力をRSSに-

補足


Java#Jakarta


*1 設定ファイルcommons-logging.properteis 、あるいは java vm の環境変数-Dorg.apache.commons.logging.Log=×× で、明示的に指定することもできます。

添付ファイル: filelogging.png 4114件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS   sitemap
Last-modified: 2013-02-09 (土) 02:09:51 (4328d)
Short-URL: http://at-sushi.com/pukiwiki/pukiwiki.php?cmd=s&k=65c74efb6c
ISBN10
ISBN13
9784061426061