8

根据c3p0 文档,您可以手动指定日志的位置,无论是通过 JDK 1.4 日志记录、Log4j 还是通过 System.out。我正在运行 SLF4J,所以我在我的应用程序中包含org.slf4j.jul-to-slf4j并调用SLF4JBridgeHandler.install()以强制所有 Java util 日志记录通过 SLF4J。此外,我在我的c3p0.properties文件中包含以下属性:

com.mchange.v2.log.MLog = com.mchange.v2.log.jdk14logging.Jdk14MLog

根据文档,这将强制 c3p0 登录到 JDK 1.4 日志,进而将日志记录到 SLF4J。这确实有点作用,但我仍然看到一些日志命中System.err

示例 1:

17:24:32.648 [main] INFO  com.mchange.v2.log.MLog - MLog clients using java 1.4+ standard logging.
Jul 27, 2011 5:24:32 PM com.mchange.v2.log.MLog <clinit>
INFO: MLog clients using java 1.4+ standard logging.
Jul 27, 2011 5:24:32 PM com.mchange.v2.c3p0.C3P0Registry banner
INFO: Initializing c3p0-0.9.1.2 [built 21-May-2007 15:04:56; debug? true; trace: 10]
17:24:32.754 [main] INFO  com.mchange.v2.c3p0.C3P0Registry - Initializing c3p0-0.9.1.2 [built 21-May-2007 15:04:56; debug? true; trace: 10]

上面的第 1 行和第 6 行被写入 SLF4J,其他的被写入System.err.

示例 2:

Jul 27, 2011 5:24:33 PM com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource getPoolManager
INFO: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> z8kflt8huk1hupkhyfms|13b33a0e, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> org.sqlite.JDBC, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> z8kflt8huk1hupkhyfms|13b33a0e, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:sqlite:/tmp/floodstream.db, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 1800, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 10, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> null, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ]
17:24:33.603 [main] INFO  com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource - Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> z8kflt8huk1hupkhyfms|13b33a0e, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> org.sqlite.JDBC, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> z8kflt8huk1hupkhyfms|13b33a0e, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:sqlite:/tmp/floodstream.db, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 1800, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 10, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> null, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ]

上面的前两行记录到System.err,这根本没有任何意义,因为它也按预期记录到 SLF4J。

有没有办法让我禁用System.err从 c3p0 登录的功能?

4

5 回答 5

9

我建议尝试一下 log4j 绑定,并配置 c3p0 以使用它。

java.util.logging 是我用过的最令人困惑的事情之一。

于 2011-07-28T01:45:53.000 回答
3

添加以下依赖关系可以解决一些问题,但不是全部。

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>log4j-over-slf4j</artifactId>
    <version>1.7.2</version><!-- Or whatever you want/need... -->
</dependency>

除此之外,您还需要绕过此文件中令人讨厌的逻辑:

https://github.com/jboss-logging/jboss-logging/blob/master/src/main/java/org/jboss/logging/LoggerProviders.java#L93

通过提供这个空类:

org.apache.log4j.Hierarchy

关于这个问题的一些辩论可以在这里找到:

https://issues.jboss.org/browse/JBLOGGING-65

为此,我计划创建一个依赖于 log4j-over-slf4j 的单个类依赖项,但是它在一个项目中按原样工作。我现在可以从 slf4j-nop 切换到 slf4j-simple 到 logback 并从我自己的代码和 Hibernate/C3P0 中获得预期的结果。

于 2013-02-18T09:22:49.617 回答
3

由于接受的答案是编写的(大约三年前),因此在工件的 0.2.5 版本中添加了对 slf4j 登录任何后端的直接支持mchange-commons-java,这就是c3p0 文档使用的内容

例如:' com.mchange.v2.log.MLog = com.mchange.v2.log.slf4j.Slf4jMLog'

但是... c3p0 的 Maven Central (0.9.2.1) 中的最新稳定版本不使用该版本。您必须至少升级到 0.9.5-pre2 才能使用该配置。最新的未发布版本是 0.9.5-pre7

这将避免必须:

  1. 将您的整体日志记录后端更改为 log4j,或者
  2. 使用“双跳”将您的登录路由到另一个答案中提供的网桥。

这就是我们为路由到 slf4j 和 logback 所做的事情。然而,在一个应用程序中,我们仍然需要使用 log4j 桥接器,直到hibernate-c3p0发布更新 c3p0 版本的 hibernate 的新版本。

我怀疑这是 FredCooke 的回答所引用的问题之一……但它可能会混淆两个问题。Hibernate 将 jboss-logging 依赖项带到了类路径中,但如果它存在,它将智能地使用 logback。然而,c3p0 需要额外配置com.mchange.v2.log.MLog = com.mchange.v2.log.log4j.Log4jMLog以将其日志条目发送到 log4j,然后将被 'log4j => slf4j' 网桥捕获。

于 2014-03-31T03:45:16.060 回答
2

如果您使用log4j-over-slf4j,c3p0 的 MLog 将记录到那个“假” log4j,它又将是 slf4j,那么您可以使用您喜欢的任何提供程序来 slf4j 的输出。

编辑:当我使用它并提交这个答案时,这很有效,但几个月后他们特别打破了这个。请参阅FredCooke回答中必要的额外修改。

于 2012-04-02T01:53:05.590 回答
-3

您可以使用 System.setErr() 使 System.err 指向另一个 PrintStream。它不会修改 C3PO,但日志输出输出将出现在您想要的位置。

于 2011-07-28T00:46:34.267 回答