然後到 Configuration 來複製,也可以照裡面的教學,但我修改成如下:
public class App { private static final Logger logger = LogManager.getLogger(App.class); public static void main(final String... args) { logger.trace("a"); logger.debug("b"); logger.info("c"); logger.warn("d"); logger.error("e"); logger.fatal("f"); } }
※注意 Logger 要 import 的包為 org.apache.logging.log4j.Logger
※排的順序是有原因的,logger有階層關係,看 architecture 中間偏下一點點有一張叫 LoggerConfig Level 的表,看直的
※執行後,console印出來如下:
ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.
最後只有印出 e 和 f
※因為還沒設定,所以有警告,但已有預設值了,所以還是能輸出,但如果想用自己設定的,可在 classpath 放一個 xml 檔,叫 log4j2.xml,上面的 Configuration 連結有說明 Automatic Configuration,沒設時是走第10條規則,現在是用第9條的方式,內容可到 Configuration 複製(JSON、YAML、properties 也有範例),如下:
※log4j2.xml
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" /> </Console> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="Console" /> </Root> </Loggers> </Configuration>
※Configuration 下有 Appenders 和 Loggers,因為 Root level 設成 error,所以 error 以下的才會印出來,Configuration 的 status 也有類似的東西,但是針對 log4j 內部的輸出,打 trace 就會印出很多,其他屬性可參考官網
※AppenderRef 的 ref 要對應 name 名稱,否則會報錯
※Appenders 有 20 多個可以用,官網都有貼範例,如 AsyncAppender,可以在 Appenders 下,增加 Async (不用打Appender) ,依此類推,至於屬性,每個表也都有
※假設想在 D 槽輸出日誌,可增加如下的設定
<Configuration status="WARN"> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" /> </Console> <File name="MyFile" fileName="D:/xxx.log"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> </File> </Appenders> <Loggers> <Root level="error"> <AppenderRef ref="Console" /> <AppenderRef ref="MyFile" /> </Root> </Loggers> </Configuration>
※AppenderRef 的 ref,可視情況增加或減少,如不想輸出到控制台,就註解
※會用附加的方式到檔案裡
※PatternLayout 的 pattern 可參考 Layouts 的 PatternLayout
※PatternLayout 格式
%d{HH:mm:ss,SSS}:時間,還有很多,看官網%-5p:p 也可用 level 表示,格式有5格,加「-」是左邊對齊,不加是右邊,如右邊對齊如下:
DEBUG
INFO
%t:執行的是哪一隻thread
%F:file name,檔案名稱
%L:line,行數
%m:訊息,就是我打的a~f,也可用 %msg、%message
%n:換行
%C:包+類別名稱,像我是「test.log4j2.App」,花括號表示從右邊以「.」為一個單位,
所以2表示log4j2.App,如下:
我將第一行改成如下:private static final Logger logger = LogManager.getLogger("www.google.com.tw");
然後pattern改成「%c{3} %C %d{yyyy-MM-dd} %L%n」
以下是結果:
google.com.tw test.log4j2.App 2016-03-24 14
google.com.tw test.log4j2.App 2016-03-24 15
google.com.tw test.log4j2.App 2016-03-24 16
google.com.tw test.log4j2.App 2016-03-24 17
google.com.tw test.log4j2.App 2016-03-24 18
google.com.tw test.log4j2.App 2016-03-24 19
※在 Web 環境使用 log4j2
官方文件下 log4j-core 時,會依賴 log4j-api,但 log4j-web 並沒有,所以還得去下載
注意 container 的版本
※web.xml
<context-param> <param-name>log4jConfiguration</param-name> <param-value>/WEB-INF/log4j2.xml</param-value> </context-param> <listener> <listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class> </listener> <filter> <filter-name>log4jServletFilter</filter-name> <filter-class>org.apache.logging.log4j.web.Log4jServletFilter</filter-class> </filter> <filter-mapping> <filter-name>log4jServletFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> <dispatcher>ERROR</dispatcher> <dispatcher>ASYNC</dispatcher><!-- Servlet 3.0 w/ disabled auto-initialization only; not supported in 2.5 --> </filter-mapping>
※如果 container 的版本夠高 (Tomcat 7(含) 以上,但7.0.43有bug),只要寫 context-param 就可以了,又如果設定檔放在 classpath 裡,而且叫 log4j2.xml,那連 context-param 也不用寫(最上面的 Configuration 連結的 10 條規則其中之一)
※都是官方複製的,唯一改的地方就是放配置檔的路徑
※如果設定沒成功,和沒 Web 時很像,只會印出 error 以下層級,但不會有警告
※官方還提供一個開關,要關閉自動初始化 log 嗎?如下:
※
<context-param> <param-name>isLog4jAutoInitializationDisabled</param-name> <param-value>true</param-value> </context-param>
※true 代表關閉,此時不會去讀取設定檔,所以還是會有預設的 error 以下的層級
※API
官網連結※代替參數、lambda
public class TestLog4j2 { private static final Logger logger = LogManager.getLogger(TestLog4j2.class); @Test public void bruceTest() { logger.info("replace1= {} {}", "a", "b"); logger.info("replace2= {} {}", "a"); logger.info("replace3= {}", "a", "b"); logger.info("lambda1= {}", () -> array()); logger.info("lambda2= {}", () -> System.getProperties()); logger.info("lambda3= {}", System::getProperties); } public String[] array() { return new String[] { "xxxx", "oooo" }; } }
※使用 {} 代替
※lambda 只會佔用1個 {},但 lambda 必需 log4j 2.4以上才有支援
※注意 Supplier 已被改寫
※官網說使用 lambda 不用顯式判斷層級,我無法理解
層級有開就印,沒開就不印,不管加不加判斷式,結果都一樣,不知道它在說什麼?
※格式化、混合
public class TestLog4j2 { public static final Logger logger = LogManager.getFormatterLogger(TestLog4j2.class); @Test public void bruceTest() { logger.info("format1= %1$s born in %2$tm %2$te,%2$tY", "bruce", new Date()); logger.info("format2= %,d", Integer.MAX_VALUE); logger.printf(Level.INFO, "mixing= %1$s born in %2$tm %2$te,%2$tY", "bruce", new Date()); } }
※混合的意思表示使用 getFormatterLogger 和 getLogger 都可以使用 $1 這種東西,但如果使用getFormatterLogger,那 {} 就失效了
沒有留言:
張貼留言