如何清理 Log4j 中的日志消息以将其保存在数据库中
我正在尝试将日志消息保存到中央数据库。为了做到这一点,我在 log4j 的 xml 配置中配置了以下 Appender:
<appender name="DB" class="org.apache.log4j.jdbc.JDBCAppender">
<param name="URL" value="jdbc:postgresql://localhost/logging_test" />
<param name="user" value="test_user" />
<param name="password" value="test_password" />
<param name="sql" value="INSERT INTO log_messages ( log_level, message, log_date ) VALUES ( '%p', '%m', '%d{yyyy-MM-dd HH:mm:ss}' )" />
</appender>
这工作正常,除了某些消息包含 ',然后 Appender 失败。
有没有简单的方法可以做到这一点?
I'm trying to save log messages to a central database. In order to do this, I configured the following Appender in log4j's xml configuration:
<appender name="DB" class="org.apache.log4j.jdbc.JDBCAppender">
<param name="URL" value="jdbc:postgresql://localhost/logging_test" />
<param name="user" value="test_user" />
<param name="password" value="test_password" />
<param name="sql" value="INSERT INTO log_messages ( log_level, message, log_date ) VALUES ( '%p', '%m', '%d{yyyy-MM-dd HH:mm:ss}' )" />
</appender>
This works fine, except some of the messages contain ', and then the appender fails.
Is there an easy way to do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
我建议创建一个自定义附加程序并覆盖
flushBuffer
和execute
方法,您可以在其中转义字符串或使用PreparedStatement
:解释为什么需要覆盖
flushBuffer
- 附加程序将LogEvent
对象放入缓冲区中,该缓冲区稍后会刷新到目标(在本例中为数据库)。此处,flushBuffer
方法使用getLogStatement
和(通过execute
)普通的Statement
。您可以完全替换该行为。查看当前源代码然后注册您的appender,而不是
JDBCAppender
。I'd suggest creating a custom appender and overriding the
flushBuffer
andexecute
methods where you can escape your strings or usePreparedStatement
:To explain why you need to override
flushBuffer
- the appender putsLogEvent
objects into a buffer which is later flushed towards the target (database in this case). Here, theflushBuffer
method usesgetLogStatement
and (viaexecute
) a normalStatement
. You can replace that behaviour completely. Have a look a the current source codeThen register your appender istead of
JDBCAppender
.看看这个非官方的 Log4J JDBCAppender 它修复了这个问题并在阿帕奇 2.0 许可证。引用其功能与
org.apache.log4j.jdbc.JDBCAppender
进行比较:或者,您应该认真考虑此选项,从 log4j 切换到其后继者, logback(这就是事情发生的地方),它有一个
DBAppender
使用PreparedStatement
(请参阅 sources),可以使用 JNDI 数据源、连接池(这是一个很大的优点)等。了解更多有关此附加程序的信息,请参阅在线手册 http://logback.qos.ch/手册/appenders.html#DBAppenderHave a look at this non official Log4J JDBCAppender which fixes this issue and is distributed under the Apache 2.0 license. Quoting its features in comparision to
org.apache.log4j.jdbc.JDBCAppender
:Or, and you should seriously consider this option, switch from log4j to its successor, logback (this is where things happen) which has a
DBAppender
that usesPreparedStatement
(see the sources), that can use a JNDI datasource, connection pooling (this is a big plus), etc. For more information about this appender, refer to the online manual http://logback.qos.ch/manual/appenders.html#DBAppender我不熟悉 log4j 或 JDBC,但我知道 JDBC 支持准备好的语句。也许有一种方法可以将其与 JDBCAppender 一起使用
I'm not familiar with log4j or JDBC, but I do know JDBC supports prepared statements. Perhaps there is a way to use that with the JDBCAppender
我通过以下方式解决了这个问题:
复制名为
ACMEJDBCAppender
的JDBCAppender
源代码覆盖
getLogStatement(LoggingEvent event)
方法,克隆旧事件并向新事件提供转义消息。从 oop 的角度来看,这不是最干净的解决方案,但它确实有效。希望有帮助。
i solved the thing in the following way :
Copied the source code of the
JDBCAppender
calledACMEJDBCAppender
override the
getLogStatement(LoggingEvent event)
method, cloning the old event and providing the new one with the escaped message.Not the cleanest solution from the oop point of view but it does the work. Hope it helps.
根据 Javadocs,官方的JDBCAppender功能相当有限,尤其是没有很好的方法来处理这个问题。
解决这个问题的一种方法是使用替代的附加程序,例如这个,其目的是在功能上与 Log4J 兼容,但工作除外。
As per the Javadocs, the offical JDBCAppender is quite limited, and in particular has no good way of dealing with this issue.
One way around it is to use an alternative appender, such as this one which aims to be functionally compatible with the Log4J one except, you know, work.
要解决记录到 Oracle 的此问题,您可以使用 Oracle 的 quote 运算符。
将引号运算符括在 %m 周围(即 q#'%m'#)
例如:
To get around this problem logging to Oracle, you can use Oracle's quote operator.
Wrap the quote operator around %m (i.e. q#'%m'#)
For example:
Joao,抱歉迟到了,但这里是:
希望有帮助!
Joao, sorry for being late, but here it is:
Hope it helps!
如果您使用的是 SQL Server,则可以使用以下
命令将问题转移到双引号上。如果您的消息中没有双引号,这可以解决问题。
If you are using SQL server you can use the following
Which shifts the problem to double quotes. If you don't have double quotes in your messages this could solve the problem.
对于 postgresql,使用 $$
示例:$$%m$$
For postgresql, use $$
Example: $$%m$$