Log4j2 进阶使用

在我前一篇文章Log4j2 简单使用中介绍了一些Log4j2的简单使用方法。下面来做一些进阶介绍。

使用属性

在复杂的项目中,可能有一些约定的属性比如项目名称、配置文件路径等等。这些属性可能会在多个日志的配置中用到。这样就可以将这些属性配置到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,发现出现如下输出。我们成功的定义了一个属性并在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="INFO">
    <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,这里列出了所有的布局和布局对应的属性。

HTML日志

Appender配置

除了我们用到的控制台和文件之外,还有很多Appender,可以满足我们的大部分需求。下面介绍一个非常实用的Appedner——RollingRandomAccessFileAppender,这个Appender会将日志写入文件,当满足条件时还会执行“rollover”操作,也就是将旧日志打包为一个压缩文件并创建一个新文件用来记录日志。

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
    <properties>
        <property name="log_path">
            D:\Desktop
        </property>
    </properties>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
        <RollingRandomAccessFile
                name="RollingRandomAccessFile"
                fileName="${log_path}\log.txt"
                filePattern="${log_path}\logs/app-%d{yyyy-MM-dd}-%i.log.zip">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="250 MB"/>
                <OnStartupTriggeringPolicy/>
            </Policies>
        </RollingRandomAccessFile>
    </Appenders>
    <Loggers>
        <Root level="debug">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="RollingRandomAccessFile"/>
        </Root>
    </Loggers>
</Configuration>

RollingRandomAccessFile节点有一个filePattern属性,指定打包的日志文件的格式。还有一个Policies节点,指定什么之后执行rollover。常用的有这么三个策略:

  • OnStartupTriggeringPolicy 程序启动时候执行一次rollover
  • SizeBasedTriggeringPolicy 日志文件到达指定大小是执行rollover,单位可以使KB、MB、GB。
  • TimeBasedTriggeringPolicy 当日期不匹配的时候执行rollover。例如上面定义的filePattern是${log_path}\logs/app-%d{yyyy-MM-dd}-%i.log.zip,日期格式包含年月日,那么就会每天执行一次rollover。它有两个可定义的属性,一个是interval,表示rollover的间隔,单位是日期的最小单位。比如如果日期是%d{yyyy-MM-dd-HH},那么interval="6"意思就是每隔六个小时。另一个属性是modulate,指定是否调整rollover的间隔。假如现在是上午3点,间隔是4个小时,当modulate为false的时候下次rollover就是上午七点,以此类推,如果modulate是true下次rollover就是上午4点,然后以此类推。

除了这几个我们知道的Appender之外,还有许多其他的Appender,可以将日志输出至SQL数据库、NoSQL数据库,电子邮件等多种目的地。详细情况参见Log4j2 - Appenders

过滤器

Log4j2还支持过滤器功能,可以定义为全局、也可以定义到Appender或者Logger上。过滤器支持时间、日志级别、日志内容等多种过滤方式。详细的过滤器类型和用法,参见Log4j2 - Filters

下面的配置文件定义了一个日志级别过滤器ThresholdFilter,将error以上的日志信息输出到文件上。所有过滤器都有两个属性onMatch和onMismatch,指定匹配过滤器和不匹配过滤器时候执行的操作,有三个取值ACCEPTDENYNEUTRAL

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
    <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,这需要使用LogManager.getFormatterLogger()语句。

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级别和ENTEREXIT标记记录日志。由于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)

以上就是一些Log4j2的进阶用法。由于Log4j2框架的内容实在太多,我完全写不过来,所以就此打住了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,103评论 18 139
  • log4j是一个被广泛使用的Java日志记录框架,通过使用该框架,我们可以在自己的项目中根据自身需求灵活配置日志输...
    LilacZiyun阅读 5,817评论 0 7
  • 在应用程序中添加日志记录总的来说基于三个目的:监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析...
    时待吾阅读 4,817评论 1 13
  • 在应用程序中添加日志记录总的来说基于三个目的:监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析...
    时待吾阅读 4,908评论 0 6
  • Log Java日志:(slf4j、log4j、logback、common-logging ) slf4j 是规...
    年少懵懂丶流年梦阅读 17,283评论 1 11