升级到 slf4j 2.0.13、logback 1.5.6 和 logback-db 1.2.11.1 后,之前正常的 logback XML 配置失败了。据我所知,框架正在尝试在初始化 DriverManagerConnectionSource 之前初始化记录器。我怀疑我错过了新的配置要求。
我已将配置文件与位于 https://logback.qos.ch/manual/appenders.html 的 DBAppender 示例进行了比较
当我追踪源代码时,
DBAppenderBase.start()
包含这一行:
DBUtil.getDialectFromCode(connectionSource.getSQLDialectCode());
connectionSource(
DriverManagerConnectionSource
的实例)包含 null 作为 SQLDialectCode
。当我深入研究时,DriverManagerConnectionSource
应该根据connectionSource.url标签中提供的URL在其SQLDialectCode
方法中设置start()
。我在调试器中使用了断点来确定 DriverManagerConnectionSource.start()
永远不会被调用。
我不可能是唯一使用过 DBAppender 的人,所以我想知道自从我们上次将 POM 引用更新为 logback 以来,配置要求发生了哪些变化。
pom.xml:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.13</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.5.6</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.5.6</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
<version>1.4.14</version>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>7.4</version>
</dependency>
<dependency>
<groupId>ch.qos.logback.db</groupId>
<artifactId>logback-classic-db</artifactId>
<version>1.2.11.1</version>
</dependency>
<dependency>
<groupId>ch.qos.logback.db</groupId>
<artifactId>logback-core-db</artifactId>
<version>1.2.11.1</version>
</dependency>
Java代码:
package com.me.myApp;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@WebListener
public class MyContextListener implements ServletContextListener {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public void contextInitialized(ServletContextEvent sce) {
System.setProperty("my.web.container", sce.getServletContext().getServerInfo());
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
logger.info("Shutting down.");
}
}
XML配置:
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds">
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>
<property file="/my/properties/my-datastore.properties"/>
<!-- To enable JMX Management -->
<jmxConfigurator />
<!-- Notification Appender -->
<appender name="me.notification.appender" class="ch.qos.logback.classic.db.DBAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
<driverClass>org.postgresql.Driver</driverClass>
<url>jdbc:postgresql://me.myapp.com:5432/mydb</url>
<user>postgres</user>
<password>postgres</password>
</connectionSource>
<encoder>
<pattern>%-5level %logger{0} - %msg%n</pattern>
<pattern>Id : %X{Id},Name : %X{Name},ModelName : %X{ModelName} %thread %date{ISO8601} %-5level %logger{5} - %msg%n</pattern>
</encoder>
</appender>
<logger name="me.notification" level="info">
<appender-ref ref="me.notification.appender" />
<appender-ref ref="logFile" />
</logger>
</configuration>
基于此 XML 配置,Logback 代码没有执行我所期望的操作:
public abstract class DBAppenderBase<E> extends UnsynchronizedAppenderBase<E> {
protected ConnectionSource connectionSource;
protected boolean cnxSupportsGetGeneratedKeys = false;
protected boolean cnxSupportsBatchUpdates = false;
protected SQLDialect sqlDialect;
protected abstract Method getGeneratedKeysMethod();
protected abstract String getInsertSQL();
@Override
public void start() {
if (connectionSource == null) {
throw new IllegalStateException("DBAppender cannot function without a connection source");
}
sqlDialect = DBUtil.getDialectFromCode(connectionSource.getSQLDialectCode());
if (getGeneratedKeysMethod() != null) {
cnxSupportsGetGeneratedKeys = connectionSource.supportsGetGeneratedKeys();
} else {
cnxSupportsGetGeneratedKeys = false;
}
cnxSupportsBatchUpdates = connectionSource.supportsBatchUpdates();
if (!cnxSupportsGetGeneratedKeys && (sqlDialect == null)) {
throw new IllegalStateException(
"DBAppender cannot function if the JDBC driver does not support getGeneratedKeys method *and* without a specific SQL dialect");
}
...
// all nice and dandy on the eastern front
super.start();
}
有几个相互影响的问题,每个问题(单独)都会导致相同的症状 (
DBAppender cannot function if the JDBC driver does not support getGeneratedKeys method and without a specific SQL dialect
),我可以在调试器的帮助下跟踪这些问题。