如何配置 Log4j2 的 JDBCAppender

576 阅读3分钟

学习配置Log4j2提供的JDBCAppender,它使用标准的JDBC将日志事件写入一个关系数据库表。

JDBCAppender从配置的连接工厂或JNDI数据源获取数据库连接。然后,它使用提供的列配置在日志表中插入新的行,每次执行日志语句。

1.1.简介

在本教程中,我们使用的是内存数据库H2

  • 当演示运行时,它会创建内存数据库并执行一个模式文件来创建一个新的表EVENT_LOGS。这个表将被用来存储日志事件。在你的应用程序中,你可能有一个持久的数据库,所以你可以跳过模式文件的部分。
  • 然后我们执行一些日志语句。这些语句被记录在控制台中,同时也被记录在数据库中。
  • 我们可以在控制台日志中验证日志语句和插入查询,因为我们已经启用了H2数据库的跟踪日志。你必须在你的生产环境中禁用它。
  • 不要忘记使用数据库连接池,否则日志记录将在性能方面付出很大的代价。

2.2.部署

对于这个简单的演示应用程序,我们只有绝对需要的依赖性。

<dependency>
	<groupId>org.apache.logging.log4j</groupId>
	<artifactId>log4j-core</artifactId>
	<version>2.14.1</version>
</dependency>

<dependency>
	<groupId>com.h2database</groupId>
	<artifactId>h2</artifactId>
	<version>2.0.202</version>
</dependency>

<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-dbcp2</artifactId>
	<version>2.9.0</version>
</dependency>

3.连接工厂

让我们从连接工厂开始,它将在我们想把事件插入数据库时提供连接。

注意以下属性的使用。

  • TRACE_LEVEL_SYSTEM_OUT- 用于启用H2的跟踪记录。
  • INIT=RUNSCRIPT FROM- 用于在应用程序开始时执行模式文件。
import java.sql.Connection;
import java.sql.SQLException;

import org.apache.commons.dbcp2.BasicDataSource;

public class LogsStoreConnectionFactory 
{
	private static BasicDataSource dataSource;

	private LogsStoreConnectionFactory() {
	}

	public static Connection getConnection() throws SQLException {
		if (dataSource == null) {
			dataSource = new BasicDataSource();
			dataSource.setUrl("jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=2;INIT=RUNSCRIPT FROM 'classpath:schema.sql'\\;");
			dataSource.setDriverClassName("org.h2.Driver");
			dataSource.setUsername("sa");
			dataSource.setPassword("");
		}
		return dataSource.getConnection();
	}
}
create table EVENT_LOGS (
    ID varchar(50) primary key,
    DATE_TIME timestamp,
    CLASS varchar(100),
    LEVEL varchar(10),
    MESSAGE TEXT,
    EXCEPTION TEXT
);

4.Log4j2配置

是时候映射数据库中的表名和列了。

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
	<Appenders>
		<Console name="Console" target="SYSTEM_OUT">
			<PatternLayout
				pattern="%d{yyyy-MMM-dd hh:mm:ss a} %level %c - %m %n" />
		</Console>
		<JDBC name="dbLogsStore" tableName="EVENT_LOGS">
		
			<!-- If Using then JNDI DateSource -->
			<!-- <DataSource jndiName="java:/comp/env/jdbc/LoggingDataSource" /> -->
			
			<ConnectionFactory 
                                class="com.howtodoinjava.demo.jdbcappender.LogsStoreConnectionFactory" 
                                method="getConnection" />
			<Column name="ID" pattern="%u" />
			<Column name="DATE_TIME" isEventTimestamp="true" />
			<Column name="CLASS" pattern="%logger" />
			<Column name="LEVEL" pattern="%level" />
			<Column name="MESSAGE" pattern="%message" />
			<Column name="EXCEPTION" pattern="%ex{full}" isClob="true"/>
		</JDBC>
	</Appenders>

	<Loggers>
		<Root level="trace">
			<AppenderRef ref="Console" />
			<AppenderRef ref="dbLogsStore" />
		</Root>
	</Loggers>

</Configuration>

5.演示

让我们来运行这个演示。

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class JDBCAppenderExample {
	private static final Logger logger = LogManager.getLogger(JDBCAppenderExample.class);

	public static void main(String[] args) 
	{
		logger.info("JDBCAppender Example ");
		try {
			logger.debug("Demo Statement");
			
			int i = 1/0;
			
		} catch (Exception e) {
			logger.error("Runtime error", e);
		}
	}
}

检查控制台的日志。

/*SQL #:1 t:14*/RUNSCRIPT FROM 'classpath:schema.sql';
2021-12-07 23:39:21 jdbc[3]: 
/**/Connection conn0 = DriverManager.getConnection("jdbc:h2:mem:testdb; TRACE_LEVEL_SYSTEM_OUT=2;INIT=RUNSCRIPT FROM 'classpath:schema.sql'\\;", "SA", "");
...
...
2021-Dec-07 11:39:21 pm DEBUG com.howtodoinjava.demo.jdbcappender. JDBCAppenderExample - Demo Statement 
2021-12-07 23:39:21 jdbc[3]: 
/*SQL l:88 #:1*/insert into EVENT_LOGS (ID,DATE_TIME,CLASS,LEVEL,MESSAGE,EXCEPTION) values (?,?,?,?,?,?) {1: 'cd4e6b02-5788-11ec-a719-70cf49366217', 2: TIMESTAMP '2021-12-07 23:39:21.328', 3: 'com.howtodoinjava.demo.jdbcappender.JDBCAppenderExample', 4: 'DEBUG', 5: 'Demo Statement', 6: ''};
...
...
2021-Dec-07 11:39:21 pm ERROR com.howtodoinjava.demo.jdbcappender. JDBCAppenderExample - Runtime error 
java.lang.ArithmeticException: / by zero
	at com.howtodoinjava.demo.jdbcappender. JDBCAppenderExample.main(JDBCAppenderExample.java:15) [classes/:?]
2021-12-07 23:39:21 jdbc[3]: 
/*SQL l:88 #:1*/insert into EVENT_LOGS (ID,DATE_TIME,CLASS, LEVEL,MESSAGE,EXCEPTION) values (?,?,?,?,?,?) {1: 'cd5018b3-5788-11ec-a719-70cf49366217', 2: TIMESTAMP '2021-12-07 23:39:21.329', 3: 'com.howtodoinjava.demo.jdbcappender.JDBCAppenderExample', 4: 'ERROR', 5: 'Runtime error', 6: U&'java.lang.ArithmeticException: / by zero\\000d\\000a\\0009at com.howtodoinjava.demo.jdbcappender. JDBCAppenderExample.main(JDBCAppenderExample.java:15)\\000d\\000a'};

6.总结

上面的JDBCAppender例子只是为了让你对事情的整体运作有一个非常高层次的了解。请不要在生产中使用这种配置。

请阅读Log4J2文档中更多的相关配置

学习愉快!!