log4j2日志框架配置+日志记录写入数据库log4j2日志框架配置+日志记录写入数据库 第一步配置pom文件依赖与 a
log4j2日志框架配置+日志记录写入数据库
第一步配置pom文件依赖与 application.properties 配置文件
我用的是spring-boot-starter-log4j2的日志依赖;
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<version>3.0.0</version>
</dependency>
配置好pom文件后 配置 [application.properties] 文件 在该文件里加入这个config路径就行。
logging.config=classpath:log4j2.xml
第二步 配置 [log4j2.xml] 文件
话不多说 具体解释都在配置文件的注释里,配置详情如下:
<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration status="INFO" monitorInterval="30">
<!--先定义所有的appender-->
<appenders>
<!--这个输出控制台的配置-->
<console name="Console" target="SYSTEM_OUT">
<!--输出日志的格式-->
<PatternLayout
pattern="%highlight{[%d{HH:mm:ss.SSS}] [%level] --- [%t] %logger{36} : %msg%n}{FATAL=red blink, ERROR=red, WARN=yellow bold, INFO=green, DEBUG=gray bold, TRACE=white bold}"/>
<!-- <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight{%-5level} [%t] %highlight{%c{1.}.%M(%L)}: %msg%n" />-->
</console>
<!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,这个也挺有用的,适合临时测试用-->
<File name="log" fileName="./log/liziSpark-test.log" append="false">
<!-- <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>-->
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n"/>
</File>
<!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="RollingFileInfo" fileName="./liziSparkLogs/logs/liziSpark-info.log"
filePattern="liziSparkLogs/logs/$${date:yyyy-MM}/dream-order-info-%d{yyyy-MM-dd}-%i.log">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
<!-- <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>-->
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
</RollingFile>
<!-- error日志-->
<RollingFile name="RollingFileError" fileName="./liziSparkLogs/logs/liziSpark-error.log"
filePattern="liziSparkLogs/logs/$${date:yyyy-MM}/dream-order-error-%d{yyyy-MM-dd}-%i.log">
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
</RollingFile>
<JDBC name="databaseAppender" bufferSize="20" tableName="blog_lizi_log">
<ConnectionFactory class="com.spark.common.log.ConnectionFactory" method="getDatabaseConnection"/>
<Column name="event_id" pattern="%X{id}"/>
<Column name="event_date" isEventTimestamp="true"/>
<Column name="thread" pattern="%t %x"/>
<Column name="class" pattern="%C"/>
<Column name="function_name" pattern="%M,%line"/>
<Column name="message" pattern="%m"/>
<Column name="exception" pattern="%ex{full}"/>
<Column name="level" pattern="%level"/>
<Column name="time" pattern="%d{yyyy-MM-dd HH:mm:ss.SSS}"/>
</JDBC>
</appenders>
<!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
<loggers>
<!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
<logger name="org.springframework" level="INFO"></logger>
<logger name="org.mybatis" level="INFO"></logger>
<logger name="com.baomidou.mybatisplus" level="DEBUG"></logger>
<!-- 根日志级别设为INFO,并关联多个Appender -->
<root level="all">
<appender-ref ref="Console"/>
<appender-ref ref="RollingFileInfo"/>
<appender-ref ref="RollingFileError"/>
<!-- 添加数据库日志Appender -->
<appender-ref ref="databaseAppender"/>
</root>
</loggers>
</configuration>
单独说一下 的配置内容:
这段配置是Log4j或Log4j2框架中的一部分,用于定义一个JDBC Appender(数据库日志记录器),即使用JDBC连接将日志事件写入数据库。下面是对各部分的详细解释:
<JDBC name="databaseAppender" bufferSize="20" tableName="blog_lizi_log">
: 这里定义了一个名为databaseAppender
的JDBC Appender。bufferSize="20"
指定了日志事件在批量写入数据库之前可以在内存中缓存的最大数量。tableName="blog_lizi_log"
指定了日志将被写入的数据库表名。<ConnectionFactory class="com.spark.common.log.ConnectionFactory" method="getDatabaseConnection"/>
: 指定了用于获取数据库连接的工厂类及其方法。这里的com.spark.common.log.ConnectionFactory
是自定义的连接工厂类,getDatabaseConnection
是获取数据库连接的方法。<Column>
标签定义了日志事件如何映射到数据库表的各个列:<Column name="event_id" pattern="%X{id}"/>
: 表示event_id
列的值将使用MDC(Mapped Diagnostic Context)中的id
属性填充。%X是MDC的占位符,{id}是MDC中的键名。<Column name="event_date" isEventTimestamp="true"/>
: 表示event_date
列自动使用事件发生的时间戳填充,因为isEventTimestamp="true"
。<Column name="thread" pattern="%t %x"/>
: 将线程名称和NDC(Nested Diagnostic Context)信息填充到thread
列。<Column name="class" pattern="%C"/>
: 使用记录事件的类名填充class
列。<Column name="function_name" pattern="%M,%line"/>
: 使用记录方法名和行号(%M)填充function_name
列,但注意这里的格式可能不正确,通常%line不直接与%M一起使用,需要确认具体日志框架的配置指南。<Column name="message" pattern="%m"/>
: 记录的消息内容填充message
列。<Column name="exception" pattern="%ex{full}"/>
: 异常堆栈信息(完整堆栈)填充exception
列。<Column name="level" pattern="%level"/>
: 日志级别填充level
列。<Column name="time" pattern="%d{yyyy-MM-dd HH:mm:ss.SSS}"/>
: 自定义的时间格式(年月日 时分秒 毫秒)填充time
列。
总之,这段配置指示Log4j在处理日志时,将按照定义的格式提取日志信息,然后通过com.spark.common.log.ConnectionFactory
获取数据库连接,并将这些信息写入到blog_lizi_log
表中相应的列。
第三步数据库表的建立,与db配置文件。
CREATE TABLE `blog_lizi_log` (
`id` bigint NOT NULL AUTO_INCREMENT,
`event_id` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
`event_date` datetime DEFAULT NULL,
`thread` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
`class` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
`function_name` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
`message` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
`exception` text CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci,
`level` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
`time` datetime DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=360 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC;
表的字段与xml中的jdbc的Column name要一一对应
db.properties 文件配置:
druid.url=jdbc:mysql://localhost:3306/bloglizi?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
druid.username=root
druid.password=123123
druid.driverClassName=com.mysql.cj.jdbc.Driver
druid.maxActive=10
druid.minIdle=5
注意时区与格式编码,这会影响插入数据的有可能时间不对或中文乱码
最后一步 也是最重要的一部 配置单例模式的数据库连接工厂方法
package com.spark.common.log;
import com.alibaba.druid.pool.DruidDataSource;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/**
* @className: ConnectionFactory
* @description: TODO 单例模式数据库连接工厂方法
* @author: albert_luo
* @date: 2024/05/17 18:18
* @Company: Copyright© 2024/5/17 by LuoTao
**/
public class ConnectionFactory {
private static final DataSource dataSource;
private static final String DB_PROPERTIES_PATH = "/db.properties";
static {
Properties properties = new Properties();
try (InputStream stream = ConnectionFactory.class.getResourceAsStream(DB_PROPERTIES_PATH)) {
if (stream == null) {
throw new ExceptionInInitializerError("Unable to find " + DB_PROPERTIES_PATH + " on classpath");
}
properties.load(stream);
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.configFromPropety(properties);
// 验证数据源配置是否正确,尝试获取连接
try (Connection testConnection = druidDataSource.getConnection()) {
if (testConnection != null) {
dataSource = druidDataSource;
} else {
throw new ExceptionInInitializerError("DataSource configuration failed, cannot obtain a valid connection.");
}
}
} catch (IOException | SQLException e) {
throw new ExceptionInInitializerError("Failed to initialize DataSource: " + e.getMessage() + e);
}
}
/**
* 获取数据库连接。
*
* @return 数据库连接对象
* @throws SQLException 连接数据库失败时抛出
*/
public static Connection getDatabaseConnection() throws SQLException {
return dataSource.getConnection();
}
}
实现效果:
如果觉得对你有用的话 点个关注+收藏吧! 来源自己的CSDN文章:blog.csdn.net/weixin_4469…
转载自:https://juejin.cn/post/7372376472437489703