<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mycompany</groupId> <artifactId>SLF4JExam</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>SLF4JExam</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.2</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-ext</artifactId> <version>1.7.2</version> </dependency> </dependencies> </project>
package com.mycompany.slf4jexam; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import org.slf4j.Marker; import org.slf4j.MarkerFactory; public class App { public static void main(String[] args) { Logger logger = LoggerFactory.getLogger(App.class); // バインドしているログフレームワークのマップ化コンテキストと連携 // Log 用の ThreadLocal な Map // Log4j の MDC に対応 (NDC((スタック))に対応する者は無い) MDC.put("uid", "USER01234"); logger.trace("Hello Trace"); logger.debug("Hello Debug"); logger.warn("Hello Warn"); logger.info("Hello Info"); logger.error("Hello Error"); // fatal は無い logger.info("\\{} はプレースホルダ => {} is not {}", 1, 2); logger.info("\\{} に順版を指定できない => {1} is not {0}", 1, 2); try { throw new NullPointerException("ぬるぽ"); } catch (NullPointerException e) { // logback では、設定ファイルで Marker によって出力する・しないのフィルタリングができる // たとえば ERROR レベルで、syslogMarker マーカーのついているログだけ、SYSLOG に出力して // 運用監視するとか // // <turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter"> // <Marker>REPORT</Marker> // <OnMatch>ACCEPT</OnMatch> // </turboFilter> Marker syslogMarker = MarkerFactory.getMarker("REPORT"); logger.error(syslogMarker, "エラーが発生しました", e); // 引数に throwable を入れるとスタックトレースが出る } // MDC は、処理終了時に必ず clear() する // (特に Web アプリなどで ThreadPool で Thread が使いまわされる可能性があるので) MDC.clear(); } }
<?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="trace" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d{yyyy-MMM-dd HH:mm:ss.SSS} : %-5p : %X{uid} : %m%n" /> </layout> </appender> <!-- ********************** /dev/nullへの出力 ********************** --> <appender name="NULL" class="org.apache.log4j.varia.NullAppender"> <param name="threshold" value="fatal"/> </appender> <!-- ********************** com.mycompany.slf4jexam.* のログは、STDOUT へ ********************** --> <logger name="com.mycompany.slf4jexam" additivity="false"> <!-- root および 包含するパッケージの category の設定を継承しない --> <level value="trace" /> <appender-ref ref="STDOUT" /> </logger > <!-- ********************** その他(ライブラリなど)は NULL へ ********************** --> <root> <priority value="warn" /> <appender-ref ref="NULL" /> </root> </log4j:configuration>
2013-2-08 01:27:20.056 : TRACE : USER01234 : Hello Trace 2013-2-08 01:27:20.058 : DEBUG : USER01234 : Hello Debug 2013-2-08 01:27:20.058 : WARN : USER01234 : Hello Warn 2013-2-08 01:27:20.058 : INFO : USER01234 : Hello Info 2013-2-08 01:27:20.058 : ERROR : USER01234 : Hello Error 2013-2-08 01:27:20.063 : INFO : USER01234 : {} はプレースホルダ => 1 is not 2 2013-2-08 01:27:20.063 : INFO : USER01234 : {} に順版を指定できない => {1} is not {0} 2013-2-08 01:27:20.070 : ERROR : USER01234 : エラーが発生しました java.lang.NullPointerException: ぬるぽ at com.mycompany.slf4jexam.App.main(App.java:33)
slf4j-ext にある LocLogger? を使う。メッセージのキーは enum で定義し、各国語のプロパティファイルでテンプレートを管理する
package com.mycompany.slf4jexam; import java.util.Locale; import org.slf4j.cal10n.LocLogger; public class App2 { public static void main(String[] args) { LocLogger logger = MyLoggerFactory.getLogger(App.class); logger.info(Msg.INFORM_START_ACTION, "TEST"); // LocLogger で、外部定義のメッセージテンプレートを使うときには、 // プレースホルダに順番を設定できる {0} is {1} logger.warn(Msg.BIZERR_RESERVE_SHORTAGE, "Mario Bros. Co.", 18000); // メッセージテンプレートが即値の場合には Logger とおなじ logger.debug("顧客ID={}, 売掛金={}, 回収金={}", 01234, 141400, 123400); logger.info(Msg.INFORM_END_ACTION, "TEST"); LocLogger logger2 = MyLoggerFactory.getLogger(App.class, Locale.UK); logger2.info(Msg.INFORM_START_ACTION, "TEST"); logger2.warn(Msg.BIZERR_RESERVE_SHORTAGE, "Mario Bros. Co.", 18000); logger.debug("customer_id={}, book_credit={}, claw_back={}", 01234, 141400, 123400); logger2.info(Msg.INFORM_END_ACTION, "TEST"); } }
package com.mycompany.slf4jexam; import ch.qos.cal10n.BaseName; import ch.qos.cal10n.Locale; import ch.qos.cal10n.LocaleData; @BaseName("template") @LocaleData( { @Locale("en_UK"), @Locale("ja_JP") }) public enum Msg { SYSERR_CANNOT_CONNECT_DB, BIZERR_RESERVE_SHORTAGE, INFORM_START_ACTION, INFORM_END_ACTION }
package com.mycompany.slf4jexam; import ch.qos.cal10n.IMessageConveyor; import ch.qos.cal10n.MessageConveyor; import java.util.Locale; import org.slf4j.cal10n.LocLogger; import org.slf4j.cal10n.LocLoggerFactory; public class MyLoggerFactory { public static LocLogger getLogger(Class clazz) { return getLogger(clazz, Locale.getDefault()); } public static LocLogger getLogger(Class clazz, Locale locale) { IMessageConveyor messageConveyor = new MessageConveyor(locale); LocLoggerFactory factory = new LocLoggerFactory(messageConveyor); return factory.getLocLogger(clazz); } }
SYSERR_CANNOT_CONNECT_DB=データベース接続エラー PORT={0}, SID={1} BIZERR_RESERVE_SHORTAGE={0} 向けの債権の引き当てができません。 {1} ドル不足しています INFORM_START_ACTION={0} 業務開始 INFORM_END_ACTION={0} 業務終了
SYSERR_CANNOT_CONNECT_DB=DB Connection Error PORT={0}, SID={1} BIZERR_RESERVE_SHORTAGE=the loans of {0} will not be covered by its loan-loss reserves. ${1} shortage. INFORM_START_ACTION=START {0} INFORM_END_ACTION=END {0}
NetBeans? いかす
2013-2-08 01:36:58.615 : INFO : : TEST 業務開始 2013-2-08 01:36:58.621 : WARN : : Mario Bros. Co. 向けの債権の引き当てができません。 18,000 ドル不足しています 2013-2-08 01:36:58.624 : DEBUG : : 顧客ID=668, 売掛金=141400, 回収金=123400 2013-2-08 01:36:58.624 : INFO : : TEST 業務終了 2013-2-08 01:36:58.627 : INFO : : START TEST 2013-2-08 01:36:58.628 : WARN : : the loans of Mario Bros. Co. will not be covered by its loan-loss reserves. $18,000 shortage. 2013-2-08 01:36:58.628 : DEBUG : : customer_id=668, book_credit=141400, claw_back=123400 2013-2-08 01:36:58.628 : INFO : : END TEST