通过log4j2 mongo可以实现分布式系统的日志统一管理
下面开始介绍springboot如何快速集成log4j2输出到mongodb
我的springboot版本是2.0.4.RELEASE
log4j2 mongodb依赖
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.10.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-nosql</artifactId>
<version>2.9.1</version>
</dependency>
<!--log4j2异步AsyncLogger需要这个依赖-->
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.4.2</version>
</dependency>
注意,还需要将spring-boot-starter中自带的logging去掉
<!--注意spring-boot-starter 去掉自带的logging-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
log4j2 mongodb 配置文件
log4j2.xml
需要注意 Logger 的 additivity属性
下面注释部分来自网络文章摘取,部分是我自己总结,经过验证的,这里我就不贴出验证过程了,有兴趣自己验证下吧,如果我的描述哪里有问题,希望能指出来,大家共同进步!
<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<Configuration status="OFF" monitorInterval="30">
<!--Appender 输出源,可以简单理解为配置要写到哪里怎么写-->
<!--Logger 日志分根器,可以简单理解为配置哪些信息写到哪些append里-->
<Appenders>
<!--建议bufferSize配置,减少频繁写操作。为了方便看到是否有往数据库写成功,我在这里故意设置1表示每来一条记录都刷新往NoSql写 -->
<NoSql name="mongoAppender" bufferSize="1">
<!--写到mongodb数据库名为"log"里的集合名为"log4j2"中,数据库需要先手动创建好,集合不需要手动创建,如果集合"log4j2"不存在,会自动创建-->
<!-- 本地mongodb没开启账号验证 -->
<MongoDb databaseName="log" collectionName="log4j2" server="127.0.0.1" port="27017"/>
<!-- 连接远程mongodb,需要校验账号密码,注意账号与数据库的权限问题,如果没权限会报错:
The database is not up, or you are not authenticated, try supplying a username and password to the MongoDB provider-->
<!-- <MongoDb databaseName="log" collectionName="log4j2" server="你的远程mongodb服务地址" port="你的远程mongodb服务端口"-->
<!-- username="xxx" password="xxx"/>-->
</NoSql>
<Console name="STDOUT" target="SYSTEM_OUT">
<!--筛选过滤,要打印到当前appender的日志信息 如果满足level的接收,不满足的拒绝-->
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
<!--输出格式布局,每个转换说明符以百分号(%)开头,'%'后面的转换字符有如下:-->
<!--
p (level) 日志级别
c(logger) Logger的Name
C (class) Logger调用者的全限定类名 ***
d (date) 日期
highlight 高亮颜色
l (location) 调用位置 ***
L (line) 行号
m (msg/message) 输出的内容
M (methode) 调用方法 ***
maker marker的全限定名
n 输出平台相关的换行符,如'\n' '\r\n'
pid (processId) 进程ID
level (p)日志级别
r JVM启动后经过的微秒
t (tn/thread/threadName) 线程名称
T (tid/threadId) 线程ID
tp (threadPriority) 线程优先级
x (NDC) 线程Context堆栈
-->
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %l - %msg%n" />
</Console>
</Appenders>
<Loggers>
<!--日志级别level以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--日志信息 优先让 子类Logger匹配 -->
<!--Logger 父子Logger区分,举个粟子 name为"a"的Logger 是 name为"a.b"的父Logger, 而Root的name是"" 所以Root是所有Logger的父Logger-->
<!--Logger name="mongologger"表示捕获日志信息name为mongologger或mongologger.xxx的信息,
子类Logger捕获了日志信息不会再被父Logger捕获,即使子类捕获日志信息由于level不满足不会去打印这条日志信息。-->
<!--注意 Logger 的 additivity 传递性,默认true
当additivity="true"时,表示当Logger捕获到日志信息并且日志信息的level大于等于当前Logger的属性level,
日志信息会打印到该Logger所有的appender中包括它的所有父logger的appender(不会管父logger的级别如何),
所以呢,如果Logger的additivity不设置"false"的话,很有可能会出现重复打印的哦-->
<!--AsyncLogger 是异步的,additivity需要设置为false,否则可能出现OOM,这个异步底层框架是disruptor,
如果没有disruptor3.4及以上依赖包,AsyncLogger日志会打印不出来-->
<AsyncLogger name="mongologger" level="info" additivity="false">
<!--被当前Logger捕获到的日志信息level大于等于当前Logger的level属性时写入到 mongoAppender 里-->
<!--每个Logger 可以设置多个appender ,如果有多个appender 会写入每个appender里-->
<appender-ref ref="mongoAppender"/>
</AsyncLogger>
<!--Root 的name="" , 是所有其他配置的Logger的父Logger-->
<!--如果 Root的level="DEBUG",而且没有设置子类捕获过滤如"org"之类的日志信息的话,会发现控制台会打印非常多的调试信息-->
<!--解决办法提高Root的level级别,或者设置子类Logger去捕获过滤相关不想要打印的日志信息,注意level级别给低点,并且设置additivity="false",如下粟子-->
<!--
<Logger name="org.apache.ibatis" level="DEBUG" additivity="false">
<AppenderRef ref="STDOUT" />
</Logger>
-->
<Root level="info" >
<appender-ref ref="STDOUT" />
</Root>
</Loggers>
</Configuration>
系统配置文件
application.properties
server.port=8097
##设置log4j2加载的配置文件,如果没有设置的话,默认找classpath:log4j2.xml
#logging.config=classpath:log4j2.xml
测试web类
TestController
package com.example.log4j2_mongodb_demo.controller;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author:
* @create: 2019-09-19 21:56
**/
@RestController
public class TestController {
public final static Logger logger = LogManager.getLogger("mongologger");
@RequestMapping("/test")
public String test(){
logger.info("123");
// logger.error("456");
return "";
}
}
windows本地安装mongodb以及mongodb的图形客户端navicat
如果没有可以连接的本地或远程mongondb,先安装个mongodb
我的本地系统是windows7 64位
win7 64位 mongodb安装 点这里
win7 64位 mongodb图形客户端安装 点这里 ,当然不安装mongodb图形客户端也行,可以用命令行去查询,我这里介绍的是用图形客户端看效果
注意:
安装了mongondb 后 记得新建一个数据库 log
上面配置log4j2写入的mongodb连接的是127.0.0.1 ,如果要连远程的mongdb 记得将这个配置改下
测试
启动springboot程序后,打开浏览器输入
http://127.0.0.1:8097/test
在mongodb图形客户端刷新下log数据库的集合,会发现有个log4j2集合,如下图
成功将log4j2 日志写入到了mongodb
源码
链接:https://pan.baidu.com/s/1fi9ak4ZaTKXOBZ7u8uXPBQ
提取码:vsa0