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 | Commons-Logging |
SEVERE | logging.fatal(),logging.error() |
WARNING | logging.warn() |
INFO | logging.info() |
CONFIG | |
FINE | logging.debug() |
FINER | |
FINEST | logging.trace() |
%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 | Commons-Logging |
FATAL | logging.fatal() |
ERROR | logging.error() |
WARN | logging.warn() |
INFO | logging.info() |
DEBUG | logging.debug(),logging.trace() |
<log4j:configuration> ::= <appender>+ <category>* <root>
<appender> ::= 使用Appenderクラス名 Appenderデフォルトログレベル 出力設定 <layout>? <layout> ::= 使用Layoutクラス名 書式
<root> ::= Rootデフォルトログレベル 使用Appender名+
<category> ::= 適用カテゴリ名 ログレベル 使用Appender名+
<?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>
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>
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"); } }
<?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