资讯

精准传达 • 有效沟通

从品牌网站建设到网络营销策划,从策略到执行的一站式服务

如何实现log4j2项目日志组件

这篇文章给大家分享的是有关如何实现log4j2项目日志组件的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

目前成都创新互联公司已为千余家的企业提供了网站建设、域名、虚拟空间、绵阳服务器托管、企业网站设计、揭西网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。

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

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

一、入门介绍

1、下载jar包

pox.xml


 
 org.apache.logging.log4j
 log4j-api
 2.10.0
 
 
 org.apache.logging.log4j
 log4j-core
 2.10.0
 

2、配置文件

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

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

3、一个简单的实例

xml配置:



 
 
 
 
 
 
 
 
 
 

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!

二、模块介绍

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

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

1、ConsoleAppender

输出到控制台,

参数名称

类型

描述

filter

Filter

过滤器

layout

Layout

日志输出格式

follow

boolean


direct

boolean


name

String

Appender的名称

ignoreExceptions

boolean

默认true,忽略写入异常

target

String

SYSTEM_OUT或SYSTEM_ERR,默认是SYSTEM_OUT

2、FileAppender

输出到文件,

参数

类型

描述

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)

参数

类型

描述

name

String

必须,appender的名称

ignoreExceptions

boolean

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

filter

Filter

过滤器

bufferSize

int

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

connectionSource

ConnectionSource

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

tableName

String

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

columnConfigs

ColumnConfig[]

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

columnMappings

ColumnMapping[]

必须,字段映射配置

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

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

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

参数类型描述
nameString

必须,表字段名称

patternString

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

literalString

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

isEventTimestampboolean

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

isUnicodeboolean

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

isClobboolean

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

实例:



 
 
  
  
  
  
  
  
 
 
 
 
  
 
 

(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

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



 
 
  
  
 
 
 
 
  
 
 

补充:

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

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

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

实例:

Test.java

ThreadContext.push("hello world!");

log4j2.xml

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

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

实例:

Test.java

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

log4j2.xml

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

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

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

感谢各位的阅读!关于“如何实现log4j2项目日志组件”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!


网页名称:如何实现log4j2项目日志组件
当前地址:http://www.cdkjz.cn/article/joosoc.html
多年建站经验

多一份参考,总有益处

联系快上网,免费获得专属《策划方案》及报价

咨询相关问题或预约面谈,可以通过以下方式与我们联系

大客户专线   成都:13518219792   座机:028-86922220