在项目运行过程中,常常需要进行功能调试以及用户行为的跟踪和记录,部分人习惯使用System.out,但这并不建议,它仅仅是使用方便但不便于维护也无扩展性。相比log4j的话,log4j可以控制日志信息的输送目的地、输出格式以及级别等等,使我们能够更加细致地控制日志的生成过程。

Log4j2是对Log4j1的升级,在性能和功能上有显著的改进,包括多线程中吞吐量的增强、占位符的支持、配置文件自动重新加载等

一、入门介绍

1、下载jar包

pox.xml

<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.10.0</version>
</dependency>
</dependencies>

2、配置文件

Log4j包含四个配置工厂实现:JSON、YAML、properties、XML,本文介绍常用的方式XML。

Log4j具有在初始化期间自动配置自身的能力。当Log4j启动时,它将定位类路径下所有符合名称的文件,优先级顺序:log4j2-test.properties > log4j2-test.xml > log4j2.properties > log4j2.xml

3、一个简单的实例

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="info">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>

java代码:

private static final Logger logger = LogManager.getLogger(MyApp.class);

    @Test
public void testLog4j(){
logger.info("hello world!");
} }

控制台信息

22:17:47.146 [main] INFO  MyApp - hello world!

二、模块介绍

<Configuration>

属性 描述
monitorInterval 如果文件被修改了,指定时间后会重新加载配置。单位秒,最小值是5
packages 以逗号隔开的包名列表,用于搜索插件,比如自定义filter、appender等。插件仅会加载一次,所以要想修改后生效必须重启项目
status 内部日志级别,设置值为debug可以在控制台上清晰地看到整个日志事件流程,所使用的Logger是org.apache.logging.log4j.core.LOGGER
strict  允许使用严格的XML格式。不支持JSON配置
verbose   在加载插件时启用诊断信息

<Appenders>

Log4j允许将日志请求打印到多个目的地。在log4j语言中,输出目的地称为Appender。目前,appender存在于控制台、文件、远程套接字服务器、Apache Flume、JMS、远程UNIX Syslog守护进程和各种数据库api中。以下介绍几种比较常用的appender,如需了解更多可以到官网上进行查阅。

1、ConsoleAppender

输出到控制台,<Console>

参数名称

类型

描述

filter

Filter

过滤器

layout

Layout

日志输出格式

follow

boolean

direct

boolean

name

String

Appender的名称

ignoreExceptions

boolean

默认true,忽略写入异常

target

String

SYSTEM_OUT或SYSTEM_ERR,默认是SYSTEM_OUT

2、FileAppender

输出到文件,<File>

参数

类型

描述

append

boolean

默认是true,新记录将追加到文件尾部

bufferedIO

boolean

默认是true,使用缓冲区可以显著地提高性能

bufferSize

int

当bufferedIO是true时,这个属性缓冲区大小,默认是8192字节。

createOnDemand

boolean

appender按需创建文件。只有当一个日志事件通过所有过滤器并被路由到这个appender时,appender才会创建这个文件。默认值为假

filter

Filter

一个过滤器来确定事件是否应该由这个Appender处理。使用复合过滤器可以使用多个筛选器

fileName

String

要写入的文件的名称。如果文件或它的任何父目录不存在,它们将被创建

immediateFlush

boolean

默认true,每次写入后都将有一个刷新。这将保证缓冲区的数据被写入磁盘,但可能会影响性能。

layout

Layout

日志格式

locking

boolean

文件锁,默认false

name

String

Appender的名称

ignoreExceptions

boolean

默认true,忽略写入异常

filePermissions

String

定义文件权限

例: rw------- or rw-rw-rw- etc...

fileOwner

String

定义文件所有者

fileGroup

String

定义文件组

3、JDBCAppender

JDBCAppender使用标准JDBC将日志事件写入到关系数据库表中。它可以配置为使用JNDI数据源或自定义工厂方法获得JDBC连接。无论采用哪种方法,都必须由连接池来支持。否则,日志记录性能将受到极大的影响。如果已配置的JDBC驱动程序支持批处理语句,并且将缓冲区大小配置为一个正数,那么日志事件将被批处理。

(1)<JDBC>

参数

类型

描述

name

String

必须,appender的名称

ignoreExceptions

boolean

默认true,忽略日志事件异常

filter

Filter

过滤器

bufferSize

int

如果一个大于0的整数,这将导致appender缓冲日志事件,并在缓冲区达到该大小时刷新写入数据

connectionSource

ConnectionSource

必须,可被检索到的数据库连接

tableName

String

必须,插入日志事件的数据表名

columnConfigs

ColumnConfig[]

必须,需要插入到数据库的字段,由多个<Column>元素组成

columnMappings

ColumnMapping[]

必须,字段映射配置

(2)使用<DataSource>来获得JDBC的连接,这里仅列出jndi:

参数 类型 描述
jndiName String 必需的,如已配置的jndi为jdbc/LoggingDatabase,那此处的值为java:comp/env/jdbc/LoggingDatabase。数据源必须由连接池来支持;否则,日志记录将非常缓慢。

(3)使用<Column>来指定要写入表中的哪些列,以及如何对它们进行写入。它没有SQL注入漏洞。

参数 类型 描述
name String

必须,表字段名称

pattern String

使用PatternLayout模式插入值,注:同一个Column元素中,patter、literal、isEventTimestamp3个属性只能存在一个

literal String

该值将直接包含在SQL语句中执行,比如:rand()函数将生成随机数,类似myibats中的${}

isEventTimestamp boolean

是否时间格式java.sql.Types.TIMESTAMP

isUnicode boolean

除非指定pattern,否则该属性将被忽略。如果是true,该值将插入Unicode。否则,该值将被插入非Unicode。

isClob boolean

除非指定pattern,否则该属性将被忽略。如果是true,该值将插入CLOB,否则将插入varchar、nvarchar

实例:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="error">
<Appenders>
<JDBC name="databaseAppender" tableName="dbo.application_log">
<DataSource jndiName="java:/comp/env/jdbc/LoggingDataSource" />
<Column name="eventDate" isEventTimestamp="true" />
<Column name="level" pattern="%level" />
<Column name="logger" pattern="%logger" />
<Column name="message" pattern="%message" />
<Column name="exception" pattern="%ex{full}" />
</JDBC>
</Appenders>
<Loggers>
<Root level="warn">
<AppenderRef ref="databaseAppender"/>
</Root>
</Loggers>
</Configuration>

<PatternLayout>

(1)日期,%d / %date

Pattern

示例

%d{DEFAULT}

2012-11-02 14:34:02,781

%d{ISO8601}

2012-11-02T14:34:02,781

%d{ISO8601_BASIC}

20121102T143402,781

%d{ABSOLUTE}

14:34:02,781

%d{DATE}

02 Nov 2012 14:34:02,781

%d{COMPACT}

20121102143402781

%d{HH:mm:ss,SSS}

14:34:02,781

%d{dd MMM yyyy HH:mm:ss,SSS}

02 Nov 2012 14:34:02,781

%d{HH:mm:ss}{GMT+0}

18:34:02

%d{UNIX}

1351866842

%d{UNIX_MILLIS}

1351866842781

当然你也可以自定义格式,比如 %d{yyyy-MM-dd HH:mm:ss}

(2)记录器,%c / %logger

Conversion Pattern

Logger Name

结果

%c{1}

org.apache.commons.Foo

Foo

%c{2}

org.apache.commons.Foo

commons.Foo

%c{10}

org.apache.commons.Foo

org.apache.commons.Foo

%c{-1}

org.apache.commons.Foo

apache.commons.Foo

%c{-2}

org.apache.commons.Foo

commons.Foo

%c{-10}

org.apache.commons.Foo

org.apache.commons.Foo

%c{1.}

org.apache.commons.Foo

o.a.c.Foo

%c{1.1.~.~}

org.apache.commons.test.Foo

o.a.~.~.Foo

%c{.}

org.apache.commons.test.Foo

....Foo

{?} - ?是正整数时表示从右边开始取n个部分,负整数表示从左边开始移除n个部分,那为什么%c{-10}是完整的名称我也不清楚,欢迎留言

(3)日志信息,%m / %msg / %message

(4)日志级别,%level

(5)换行符,%n

<Filter>

log4j2自带多种filter供直接使用,也可以由我们自己来定义filter:

MyFilter.java

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.ThreadContext;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.Logger;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.filter.AbstractFilter;
import org.apache.logging.log4j.message.Message; @Plugin(name = "MyFilter", category = "Core", elementType = "filter", printObject = true)
public final class MyFilter extends AbstractFilter { private final Level level; private MyFilter(Level level, Result onMatch, Result onMismatch) {
super(onMatch, onMismatch);
this.level = level;
} public Result filter(Logger logger, Level level, Marker marker, String msg, Object[] params) {
return filter(level);
} public Result filter(Logger logger, Level level, Marker marker, Object msg, Throwable t) {
return filter(level);
} public Result filter(Logger logger, Level level, Marker marker, Message msg, Throwable t) {
return filter(level);
} @Override
public Result filter(LogEvent event) {
return filter(event.getLevel());
} private Result filter(Level level) { /*
* 业务逻辑
* */ return level.isMoreSpecificThan(this.level) ? onMatch : onMismatch;
} @Override
public String toString() {
return level.toString();
} @PluginFactory
public static MyFilter createFilter(@PluginAttribute(value = "level", defaultString = "ERROR") Level level,
@PluginAttribute(value = "onMatch", defaultString = "NEUTRAL") Result onMatch,
@PluginAttribute(value = "onMismatch", defaultString = "DENY") Result onMismatch) {
return new MyFilter(level, onMatch, onMismatch);
}
}

log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" monitorInterval="5" packages="your packages" verbose="false" strict="true">
<Appenders> <Console name="Console" target="SYSTEM_OUT" ignoreExceptions="true">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %level %logger{10} - %msg%n"/>
<MyFilter level="info" onMatch="ACCEPT"/>
</Console> </Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>

补充:

在实际应用中,有时需要对用户的访问信息进行记录,比如请求参数、用户id等等。在log4j1中我们会使用MDC和NDC来存储应用程序的上下文信息,而log4j2使用ThreadContext来实现MDC和NDC两者的功能。

(1)NDC采用类似栈的机制来存储上下文信息,线程独立。

在PatternLayout中使用 %x 来输出,注意x是小写。

实例:

Test.java

ThreadContext.push("hello world!");

log4j2.xml

<Column name="tip" pattern="%x" />

(2)MDC采用类似map的机制来存储信息,线程独立。

在PatternLayout中使用 %X{userId} 来输出,注意X是大写。

实例:

Test.java

ThreadContext.put("userId","1");

log4j2.xml

<Column name="userId" pattern="%X{userId}" />

注意使用完后调用clearAll()清除上下文映射和堆栈。

api:http://logging.apache.org/log4j/2.x/javadoc.html

官网地址:https://logging.apache.org/log4j/2.x/index.html

转载请注明出处:http://www.cnblogs.com/cjh-notes/p/8017855.html

log4j2 项目日志组件的更多相关文章

  1. 日志组件二:log4j2

    一.背景 随着业务服务(Server App)逐渐增加,我们的业务系统中的日志输出面临的问题越来越多,高并发下对磁盘io这块消耗的越来越大,因此,急需要一个高性能且最好能够支持异步输出日志的日志框架, ...

  2. 使用Slf4j集成Log4j2构建项目日志系统的完美解决方案

    一.背景 最近因为公司项目性能需要,我们考虑把以前基于的log4j的日志系统重构成基于Slf4j和log4j2的日志系统,因为,使用slf4j可以很好的保证我们的日志系统具有良好的兼容性,兼容当前常见 ...

  3. Work Time Manager【开源项目】- 创建自己日志组件 2.0重构

    Hello all , 我又回来了 这次我们真是开始来聊聊开源项目里,小而有用的模块或者组件的开发思想. 同时,软件已经更新到1.60的版本了,支持新用户注册,可以不再使用统一的test账户了. 您可 ...

  4. 普通Java项目中使用Sl4j+Log4j2打印日志

        因工作需要,采用JavaFx开发了一个windows窗口程序.在开发过程中,由于没有引入日志框架,只能自己手动在控制台打印些信息,给调试带来了很多麻烦:因此决定引入日志框架.由于之前接触的项目 ...

  5. java日志组件介绍(common-logging,log4j,slf4j,logback )

    转自:http://www.blogjava.net/daiyongzhi/archive/2014/04/13/412364.html common-logging是apache提供的一个通用的日志 ...

  6. 五分钟秒懂Java日志组件

    Java中有许多种日志记录方式,有些API有占位符,有些API没占位符,初学的人可能会搞不清楚这些日志组件的由来.我一开始的时候也是很懵逼的,后来一点点弄懂了于是就又了这篇文章. 在Java中进行日志 ...

  7. Java中日志组件详解

    avalon-logkit Java中日志组件详解 lanhy 发布于 2020-9-1 11:35 224浏览 0收藏 作为开发人员,我相信您对日志记录工具并不陌生. Java还具有功能强大且功能强 ...

  8. C#组件系列———又一款日志组件:Elmah的学习和分享

    前言:好久没动笔了,都有点生疏,12月都要接近尾声,可是这月连一篇的产出都没有,不能坏了“规矩”,今天还是来写一篇.最近个把月确实很忙,不过每天早上还是会抽空来园子里逛逛.一如既往,园子里每年这个时候 ...

  9. 我心中的核心组件(可插拔的AOP)~第十五回 我的日志组件Logger.Core(策略,模版方法,工厂,单例等模式的使用)

    回到目录 之前的讲过两篇关于日志组件的文章,分别是<第一回  日志记录组件之自主的Vlog>和<第三回  日志记录组件之log4net>,而今天主要说一下我自己开发的另一种日志 ...

随机推荐

  1. HTML中动态生成内容的事件绑定问题【转载】

    转自 http://www.hitoy.org/event-binding-problem-of-dynamically-generated-content.html 由于实际的需要,有时需要往网页中 ...

  2. FTP配置的一些笔记

    1.必须关闭防火墙 iptables -F iptables -X iptables -Z vi /etc/selinux/config          SELINUX=disabled seten ...

  3. 【APP问题定位(三)】adb安装

    先来剧透一下我们需要使用的工具 bin包               一个安装目录,可以免安装直接调用adb命令 Android SDK platform tools 下面依次为大家介绍,第1个和第2 ...

  4. JSP 学习笔记

    JSP 全名为Java Server Pages,中文名叫java 服务器页面,它是在传统的 HTML 页面中插入 JAVA 代码片段和 JSP 标签形成的文件. 上一篇 Servlet 中只是讲解了 ...

  5. C#编写的艺术字类方法

    代码如下: using System;using System.Collections.Generic;using System.ComponentModel;using System.Drawing ...

  6. 整合springboot(app后台框架搭建四)

    springboot可以说是为了适用SOA服务出现,一方面,极大的简便了配置,加速了开发速度:第二方面,也是一个嵌入式的web服务,通过jar包运行就是一个web服务: 还有提供了很多metric,i ...

  7. Spring JDBC 示例

    在使用普通的 JDBC 数据库时,就会很麻烦的写不必要的代码来处理异常,打开和关闭数据库连接等.但 Spring JDBC 框架负责所有的低层细节,从开始打开连接,准备和执行 SQL 语句,处理异常, ...

  8. 后端自动化版本管理,再也不用改URL了!

    每次升级接口版本时,后端.前端.客户端都是痛苦的: 后端:要兼容旧版客户端,以前的接口不能动啊,又得写新接口.新文档了,唉! 前端:还好,就是版本号到处都是,改起来比较烦. Android:快点啊产品 ...

  9. JavaScript数据可视化编程学习(二)Flotr2,雷达图

    一.雷达图 使用雷达图显示多维数据. 如果你有多维的数据要展示,那么雷达图就是一种非常有效的可视化方法. 由于雷达图不常用,比较陌生,所以向用户解释的时候有一些难度.注意使用雷达图会增加用户认知负担. ...

  10. 如何用webgl(three.js)搭建一个3D库房-第一课

    今天我们来讨论一下如何使用当前流行的WebGL技术搭建一个库房并且实现实时有效交互 第一步.搭建一个3D库房首先你得知道库房长啥样,我们先来瞅瞅库房长啥样(这是我在网上找的一个库房图片,百度了“库房” ...