欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

log4j2 项目日志组件的实例代码

程序员文章站 2024-02-16 19:33:28
在项目运行过程中,常常需要进行功能调试以及用户行为的跟踪和记录,部分人习惯使用system.out,但这并不建议,它仅仅是使用方便但不便于维护也无扩展性。相比log4j的话...

在项目运行过程中,常常需要进行功能调试以及用户行为的跟踪和记录,部分人习惯使用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

<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"/>
  <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:

官网地址:

以上这篇log4j2 项目日志组件的实例代码就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。