使用属性
在复杂的项目中,可能有一些约定的属性比如项目名称、配置文件路径等等。这些属性可能会在多个日志的配置中用到。这样就可以将这些属性配置到Log4j2的配置文件中,方便在多个Logger中共享。
定义属性需要在配置文件中添加properties节点,然后添加多个property。
配置完成之后使用${property_name}就可以在项目中引用了。
下面的一个配置文件中PatternLayout这样。
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<properties>
<property name="logger_name">
FuckLog4j2
</property>
</properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level [${logger_name}] %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
配置完成之后,运行发现出现如下输出,成功的定义了一个属性并在Logger中使用。
18:05:09.404 [Test worker] INFO [FuckLog4j2] yitian.bean.BeanTest - Pi is 3.141592653589793
自动重新配置
有时候可能在项目运行的时候修改一些日志配置,Log4j2也支持定时重新读取配置的功能。需要在配置文件根节点也就是Configuration节点下添加一个属性monitorInterval,指定在多少秒后重新读取配置,单位是秒,最低读取间隔是5秒。
<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorInterval="30">
...
</Configuration>
布局配置
PatternLayout布局配置,这种布局会根据指定的格式化字符串将数据日志格式化成相应的字符串。
其实除了这种布局之外,还可以将日志打印为HTML、XML、YAML、CVS等多种格式的文件。
下面的配置文件定义了一个HTMLLayout,这样会把日志输出位一个HTML文件,日志内容会议表格列出。
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<properties>
<property name="log_path">
D:\Desktop
</property>
<property name="file_name">
log.html
</property>
</properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
<File name="File" fileName="${log_path}\${file_name}">
<HTMLLayout title="日志"/>
</File>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="Console"/>
<AppenderRef ref="File"/>
</Root>
</Loggers>
</Configuration>
运行程序之后会有这么一个HTML文件,打开以后大致就是这样的。
其他布局的使用方法也是类似的,添加到对应的Appender下,然后指定相应布局的属性,就可以获得对应的效果。
详细情况可以查看官方文档Log4j2 - Lyaout,这里列出了所有的布局和布局对应的属性。
过滤器
Log4j2还支持过滤器功能,可以定义为全局、也可以定义到Appender或者Logger上。
过滤器支持时间、日志级别、日志内容等多种过滤方式。详细的过滤器类型和用法,参见Log4j2 - Filters。
下面的配置文件定义了一个日志级别过滤器ThresholdFilter,将error以上的日志信息输出到文件上。
所有过滤器都有两个属性 onMatch 和 onMismatch,指定匹配过滤器和不匹配过滤器时候执行的操作,有三个取值ACCEPT(接受),DENY(否认),NEUTRAL(中立)。
<?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>
<File name="File" fileName="D:/Desktop/log.txt">
<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</File>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="Console"/>
<AppenderRef ref="File"/>
</Root>
</Loggers>
</Configuration>
其它API
前面我们使用了最简单的方式定义和使用Logger,也就是下面的两句代码。
Logger logger = LogManager.getLogger();
logger.info("info");
除了这种简单的方式,Log4j2还提供了其它API,帮助我们执行更加复杂的操作。
格式化信息
我们要在日志中输出用户名和密码两个信息,可以编写如下的语句,字符串中的{}是占位符,会被后面的实际参数替换。
logger.info("username:{} password:{}", username, password);
如果需要更精细的格式化,可以使用%-5s这样的格式化字符串,但是相应地需要一个格式化的Logger,这需要使用<code> LogManager.getFormatterLogger() </code>语句。
Logger logger = LogManager.getFormatterLogger();
String username = "root";
String password = "123456";
logger.debug("Logging in user %s with birthday %s", username, Calendar.getInstance());
logger.debug("Logging in user %1$s with birthday %2$tm %2$te,%2$tY", username, Calendar.getInstance());
logger.debug("Integer.MAX_VALUE = %,d", Integer.MAX_VALUE);
logger.debug("Long.MAX_VALUE = %,d", Long.MAX_VALUE);
日志标记
在输出日志的时候,可以为日志添加一个标记,这样在日志输出的时候就会附带上这个标记,帮助我们区分不同的日志。
调用MarkerManager.getMarker方法生成一个标记,标记必须是唯一的。然后在记录日志的时候将标记传入。
Logger logger = LogManager.getLogger();
String username = "root";
String password = "123456";
Marker marker = MarkerManager.getMarker("test");
logger.debug(marker, "username:{} password:{}", username, password);
为了能在日志输出时看到标记,我们需要在PatternLayout的pattern属性中添加%marker。
流跟踪
这需要4个方法entry()、traceEntry()、exit()、traceExit(),前两个方法用在方法的开始处,后两个方法用在方法结束时(return语句之前),一三方法为一对,二四方法为一对。
entry()和traceEntry()的区别在于,前者接受一组参数,一般情况下是所在方法的参数,后者接受一个格式化字符串和一组参数。
这几个方法会使用 trace 级别和ENTER或EXIT标记记录日志。由于traceEntry()方法能接受格式化字符串,所以这个方法更常用一些。
我们新建一个类,然后在它的方法中添加流跟踪语句。
public class MyTest {
private static Logger logger = LogManager.getLogger();
public static String test(String name, int id) {
logger.traceEntry("name:{} id:{}", name, id);
return logger.traceExit(name + ":" + id);
}
}
然后调用这个方法,就可以在日志中看到对应的流信息了。因为流信息都是TRACE级别的,所以如果日志级别是其他的级别,就无法看到这些信息了。
21:56:38.755 ENTER[ FLOW ] [Test worker] TRACE yitian.bean.MyTest - Enter name:yitian id:1
21:56:38.771 EXIT[ FLOW ] [Test worker] TRACE yitian.bean.MyTest - Exit with(yitian:1)
http://blog.csdn.net/autfish/article/details/51244787
连接给出如下内容:
按日志级别区分文件输出、 异步写日志、 输出到MongoDB、输出到Flume