我想将log4j2消息记录到关系数据库中.
JDBC appender的文档是here.我可以使用这些来源作为数据库连接提供程序:
> ConnectionFactory
> DataSource
> DriverManager
但是在某种程度上如何使用我们在整个应用程序中使用的数据源bean(com.jolbox.bonecp.BoneCPDataSource)?
解决方法:
您可以通过4个步骤完成(步骤2和3是针对Web应用程序的log4j2配置):
步骤1:创建log4j2.xml文件(不带JDBC appender)并将其放在WEB-INF文件夹中
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<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>
步骤2:将log4j2-web-2.x.jar添加到WEB-INF / lib.
这是maven repository,您可以从那里下载jar,或者如果您使用maven,则将依赖项复制粘贴到您的pom.xml.
步骤3:根据servlet api版本配置web.xml
有关更多详细信息,请参阅log4j2 documentation.以下是在servlet 2.5 Web应用程序中配置log4j的方法.
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<!-- Logg -->
<listener>
<listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
</listener>
<filter>
<filter-name>log4jServletFilter</filter-name>
<filter-class>org.apache.logging.log4j.web.Log4jServletFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>log4jServletFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<!-- /Logg -->
<!-- ... -->
</web-app>
第4步:创建一个spring bean,注入你的DataSource bean,并在@PostConstruct方法中动态添加JDBC Appender配置
这是代码示例(使用log4j 2.1和spring 3.5进行测试)
import java.sql.Connection;
import java.sql.SQLException;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.db.jdbc.ColumnConfig;
import org.apache.logging.log4j.core.appender.db.jdbc.ConnectionSource;
import org.apache.logging.log4j.core.appender.db.jdbc.JdbcAppender;
import org.apache.logging.log4j.core.config.AppenderRef;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class LogUtils{
@Autowired
private DataSource dataSource;
//inner class
class Connect implements ConnectionSource {
private DataSource dsource;
public Connect(DataSource dsource) {
this.dsource = dsource;
}
@Override
public Connection getConnection() throws SQLException {
return this.dsource.getConnection();
}
}
public LogUtils() {
System.out.println("LogUtils");
}
@PostConstruct
private void init(){
System.out.println("init LogUtils");
final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
final Configuration config = ctx.getConfiguration();
ColumnConfig[] cc = {
ColumnConfig.createColumnConfig(config, "date", null, null, "true", null, null),
ColumnConfig.createColumnConfig(config, "level", "%level", null, null, null, null),
ColumnConfig.createColumnConfig(config, "logger", "%logger", null, null, null, null),
ColumnConfig.createColumnConfig(config, "message", "%message", null, null, null, null),
ColumnConfig.createColumnConfig(config, "throwable", "%ex{short}", null, null, null, null),
ColumnConfig.createColumnConfig(config, "salarie_id", "%X{SALARIE_ID}", null, null, null, null)
} ;
Appender appender = JdbcAppender.createAppender("databaseAppender", "true", null, new Connect(dataSource), "0", "sicdb.bo_log", cc);
appender.start();
config.addAppender(appender);
LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME);
loggerConfig.addAppender(appender, null, null);
ctx.updateLoggers();
}
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
}
**限制:link to doc **
Applications sometimes have the need to customize logging separate from the actual configuration.
Log4j allows this although it suffers from a few limitations:
1. If the configuration file is changed the configuration will be reloaded and the manual changes
will be lost.
2. Modification to the running configuration requires that all the methods being called
(addAppender and addLogger) be synchronized.
As such, the recommended approach for customizing a configuration is to extend one of the standard
Configuration classes, override the setup method to first do super.setup() and then add the custom
Appenders, Filters and LoggerConfigs to the configuration before it is registered for use.