用日志来跟踪应用程序的流程有下面的好处:
进入方法的时候,可以将entry()和traceEntry()放在方法的第一个语句,这个日志方法的级别时TRACE,对应的marker名字是ENTER,是流程marker,所有打印的日志语句都以“event”开头。这两个方法的区别在于entry()方法直接接受可变参数,而traceEntry()接受一个格式化字符串和可变参数。
离开方法的时候,如果方法没有返回值,那么就调用exit()或者traceExit();如果方法具有返回值,那么就调用 exit(Object obj) or traceExit(object, new SomeMessage(object)) 。这些方法具有的级别是TRACE,具有名字为"EXIT"的marker,是流程marker,所有打印的日志欲绝都以"exit"开头。
当出现异常的时候,如果应用程序捕捉到异常,并且想要继续抛出异常,那么就调用日志组件的throw()方法进行日志输出;如果不想抛出或者不会将异常信息附加到另一个异常上,那么就使用日志组件的catch()方法。这两个方法的日志级别都是ERROR,throw()的marker的名字是" THROWING ",catch()的marker的名字是“ CATCHING ”,两个marker都是 “EXCEPTION” Marker.
下面是一个使用日志方法的典型例子:
package com.test;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import java.util.Random;
public class TestService {
private Logger logger = LogManager.getLogger(TestService.class.getName());
private String[] messages = new String[] {
"Hello, World",
"Goodbye Cruel World",
"You had me at hello"
};
private Random rand = new Random(1);
public void setMessages(String[] messages) {
logger.traceEntry(new JsonMessage(messages));
this.messages = messages;
logger.traceExit();
}
public String[] getMessages() {
logger.traceEntry();
return logger.traceExit(messages, new JsonMessage(messages));
}
public String retrieveMessage() {
logger.entry();
String testMsg = getMessage(getKey());
return logger.exit(testMsg);
}
public void exampleException() {
logger.entry();
try {
String msg = messages[messages.length];
logger.error("An exception should have been thrown");
} catch (Exception ex) {
logger.catching(ex);
}
logger.exit();
}
public String getMessage(int key) {
logger.entry(key);
String value = messages[key];
return logger.exit(value);
}
private int getKey() {
logger.entry();
int key = rand.nextInt(messages.length);
return logger.exit(key);
}
}
下面的应用调用了上面的日志类:
package com.test;
public class App {
public static void main( String[] args ) {
TestService service = new TestService();
service.retrieveMessage();
service.retrieveMessage();
service.exampleException();
}
}
在类路径下添加一个log4j2.xml文件作为配置文件,其内容如下:
<Configuration status="error">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
Console>
<File name="log" fileName="target/test.log" append="false">
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
File>
Appenders>
<Loggers>
<Root level="trace">
<AppenderRef ref="log"/>
Root>
Loggers>
Configuration>
上面的java应用和配置文件一起产生的日志会输出到文件中,其内容如下:
19:08:07.056 TRACE com.test.TestService 19 retrieveMessage - entry
19:08:07.060 TRACE com.test.TestService 46 getKey - entry
19:08:07.060 TRACE com.test.TestService 48 getKey - exit with (0)
19:08:07.060 TRACE com.test.TestService 38 getMessage - entry parms(0)
19:08:07.060 TRACE com.test.TestService 42 getMessage - exit with (Hello, World)
19:08:07.060 TRACE com.test.TestService 23 retrieveMessage - exit with (Hello, World)
19:08:07.061 TRACE com.test.TestService 19 retrieveMessage - entry
19:08:07.061 TRACE com.test.TestService 46 getKey - entry
19:08:07.061 TRACE com.test.TestService 48 getKey - exit with (1)
19:08:07.061 TRACE com.test.TestService 38 getMessage - entry parms(1)
19:08:07.061 TRACE com.test.TestService 42 getMessage - exit with (Goodbye Cruel World)
19:08:07.061 TRACE com.test.TestService 23 retrieveMessage - exit with (Goodbye Cruel World)
19:08:07.062 TRACE com.test.TestService 27 exampleException - entry
19:08:07.077 DEBUG com.test.TestService 32 exampleException - catching java.lang.ArrayIndexOutOfBoundsException: 3
at com.test.TestService.exampleException(TestService.java:29) [classes/:?]
at com.test.App.main(App.java:9) [classes/:?]
at com.test.AppTest.testApp(AppTest.java:15) [test-classes/:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.6.0_29]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) ~[?:1.6.0_29]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[?:1.6.0_29]
at java.lang.reflect.Method.invoke(Method.java:597) ~[?:1.6.0_29]
at org.junit.internal.runners.TestMethodRunner.executeMethodBody(TestMethodRunner.java:99) [junit-4.3.1.jar:?]
at org.junit.internal.runners.TestMethodRunner.runUnprotected(TestMethodRunner.java:81) [junit-4.3.1.jar:?]
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34) [junit-4.3.1.jar:?]
at org.junit.internal.runners.TestMethodRunner.runMethod(TestMethodRunner.java:75) [junit-4.3.1.jar:?]
at org.junit.internal.runners.TestMethodRunner.run(TestMethodRunner.java:45) [junit-4.3.1.jar:?]
at org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod(TestClassMethodsRunner.java:66) [junit-4.3.1.jar:?]
at org.junit.internal.runners.TestClassMethodsRunner.run(TestClassMethodsRunner.java:35) [junit-4.3.1.jar:?]
at org.junit.internal.runners.TestClassRunner$1.runUnprotected(TestClassRunner.java:42) [junit-4.3.1.jar:?]
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34) [junit-4.3.1.jar:?]
at org.junit.internal.runners.TestClassRunner.run(TestClassRunner.java:52) [junit-4.3.1.jar:?]
at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:35) [surefire-junit4-2.7.2.jar:2.7.2]
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:115) [surefire-junit4-2.7.2.jar:2.7.2]
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:97) [surefire-junit4-2.7.2.jar:2.7.2]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.6.0_29]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) ~[?:1.6.0_29]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[?:1.6.0_29]
at java.lang.reflect.Method.invoke(Method.java:597) ~[?:1.6.0_29]
at org.apache.maven.surefire.booter.ProviderFactory$ClassLoaderProxy.invoke(ProviderFactory.java:103) [surefire-booter-2.7.2.jar:2.7.2]
at $Proxy0.invoke(Unknown Source) [?:?]
at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:150) [surefire-booter-2.7.2.jar:2.7.2]
at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcess(SurefireStarter.java:91) [surefire-booter-2.7.2.jar:2.7.2]
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:69) [surefire-booter-2.7.2.jar:2.7.2]
19:08:07.087 TRACE com.test.TestService 34 exampleException - exit
将root logger的level更改为 DEBUG ,那么日志输出结果如下所示:
19:13:24.963 DEBUG com.test.TestService 32 exampleException - catching java.lang.ArrayIndexOutOfBoundsException: 3
at com.test.TestService.exampleException(TestService.java:29) [classes/:?]
at com.test.App.main(App.java:9) [classes/:?]
at com.test.AppTest.testApp(AppTest.java:15) [test-classes/:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.6.0_29]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) ~[?:1.6.0_29]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[?:1.6.0_29]
at java.lang.reflect.Method.invoke(Method.java:597) ~[?:1.6.0_29]
at org.junit.internal.runners.TestMethodRunner.executeMethodBody(TestMethodRunner.java:99) [junit-4.3.1.jar:?]
at org.junit.internal.runners.TestMethodRunner.runUnprotected(TestMethodRunner.java:81) [junit-4.3.1.jar:?]
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34) [junit-4.3.1.jar:?]
at org.junit.internal.runners.TestMethodRunner.runMethod(TestMethodRunner.java:75) [junit-4.3.1.jar:?]
at org.junit.internal.runners.TestMethodRunner.run(TestMethodRunner.java:45) [junit-4.3.1.jar:?]
at org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod(TestClassMethodsRunner.java:66) [junit-4.3.1.jar:?]
at org.junit.internal.runners.TestClassMethodsRunner.run(TestClassMethodsRunner.java:35) [junit-4.3.1.jar:?]
at org.junit.internal.runners.TestClassRunner$1.runUnprotected(TestClassRunner.java:42) [junit-4.3.1.jar:?]
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34) [junit-4.3.1.jar:?]
at org.junit.internal.runners.TestClassRunner.run(TestClassRunner.java:52) [junit-4.3.1.jar:?]
at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:35) [surefire-junit4-2.7.2.jar:2.7.2]
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:115) [surefire-junit4-2.7.2.jar:2.7.2]
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:97) [surefire-junit4-2.7.2.jar:2.7.2]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.6.0_29]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) ~[?:1.6.0_29]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) ~[?:1.6.0_29]
at java.lang.reflect.Method.invoke(Method.java:597) ~[?:1.6.0_29]
at org.apache.maven.surefire.booter.ProviderFactory$ClassLoaderProxy.invoke(ProviderFactory.java:103) [surefire-booter-2.7.2.jar:2.7.2]
at $Proxy0.invoke(Unknown Source) [?:?]
at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:150) [surefire-booter-2.7.2.jar:2.7.2]
at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcess(SurefireStarter.java:91) [surefire-booter-2.7.2.jar:2.7.2]
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:69) [surefire-booter-2.7.2.jar:2.7.2]
n.surefire.booter.SurefireStarter.runSuitesInProcess(SurefireStarter.java:91) [surefire-booter-2.7.2.jar:2.7.2]
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:69) [surefire-booter-2.7.2.jar:2.7.2]