java 如何清理 Log4j 中的日志消息以将它们保存在数据库中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2042070/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 19:06:08  来源:igfitidea点击:

How to sanitize log messages in Log4j to save them in database

javajdbclog4j

提问by Rafael

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:

我正在尝试将日志消息保存到中央数据库。为此,我在 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>

This works fine, except some of the messages contain ', and then the appender fails.

这工作正常,除了一些消息包含 ',然后附加程序失败。

Is there an easy way to do this?

是否有捷径可寻?

采纳答案by Pascal Thivent

Have a look at this non official Log4J JDBCAppenderwhich fixes this issue and is distributed under the Apache 2.0 license. Quoting its features in comparision to org.apache.log4j.jdbc.JDBCAppender:

看看这个非官方的Log4J JDBCAppender,它修复了这个问题并在 Apache 2.0 许可下分发。引用它的特点来比较org.apache.log4j.jdbc.JDBCAppender

  • Log to (relational) database
  • Flexible connection handling (does not yet support DataSource)
  • Flexible sql commands to execute actual logging
  • Prepared Statements and Stored Procedures (J2SDK 1.4+) supported
  • Enables logging of messages with special characters such as ' (single quote) and , (comma)
  • Flexible table and column structure
  • Flexible id generation
  • Multiple PatternLayout applications allowed; in one or more columns
  • Supports J2SDK 1.3, 1.4 and 1.5
  • Supports Log4j 1.2.9 and current development
  • 登录到(关系)数据库
  • 灵活的连接处理(尚不支持 DataSource)
  • 灵活的 sql 命令来执行实际日志记录
  • 支持准备好的语句和存储过程 (J2SDK 1.4+)
  • 启用带有特殊字符的消息记录,例如 '(单引号)和 ,(逗号)
  • 灵活的表和列结构
  • 灵活的 id 生成
  • 允许多个 PatternLayout 应用程序;在一列或多列中
  • 支持 J2SDK 1.3、1.4 和 1.5
  • 支持 Log4j 1.2.9 和当前开发

Or, and you should seriously consider this option, switch from log4j to its successor, logback(this is where things happen) which has a DBAppenderthat uses PreparedStatement(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 切换到它的后继,logback(这是事情发生的地方),它有一个DBAppender使用PreparedStatement(见),可以使用 JNDI 数据源,连接池(这是一个很大的plus)等。关于这个appender的更多信息,参考在线手册http://logback.qos.ch/manual/appenders.html#DBAppender

回答by Bozho

I'd suggest creating a custom appender and overriding the flushBufferand executemethods where you can escape your strings or use PreparedStatement:

我建议创建一个自定义 appender 并覆盖flushBufferexecute方法,您可以在其中转义字符串或使用PreparedStatement

public class MyJDBCAppender extends JDBCAppender {

}

To explain why you need to override flushBuffer- the appender puts LogEventobjects into a buffer which is later flushed towards the target (database in this case). Here, the flushBuffermethod uses getLogStatementand (via execute) a normal Statement. You can replace that behaviour completely. Have a look a the current source code

为了解释为什么需要覆盖flushBuffer- 附加程序将LogEvent对象放入缓冲区,然后将其刷新到目标(在这种情况下为数据库)。在这里,该flushBuffer方法使用getLogStatement和(通过execute)一个正常的Statement. 您可以完全替换该行为。看看当前的源代码

Then register your appender istead of JDBCAppender.

然后注册您的 appender 而不是JDBCAppender.

回答by Bart van Heukelom

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

我不熟悉 log4j 或 JDBC,但我知道 JDBC 支持准备好的语句。也许有一种方法可以将它与 JDBCAppender 一起使用

回答by Mattia

i solved the thing in the following way :

我通过以下方式解决了这个问题:

Copied the source code of the JDBCAppendercalled ACMEJDBCAppender

复制被JDBCAppender调用者的源代码ACMEJDBCAppender

override the getLogStatement(LoggingEvent event)method, cloning the old event and providing the new one with the escaped message.

覆盖该getLogStatement(LoggingEvent event)方法,克隆旧事件并为新事件提供转义消息。

Not the cleanest solution from the oop point of view but it does the work. Hope it helps.

从 oop 的角度来看,这不是最干净的解决方案,但它确实有效。希望能帮助到你。

protected String getLogStatement(LoggingEvent event) {

  LoggingEvent clone = new LoggingEvent(
    event.fqnOfCategoryClass,
    LogManager.getLogger(event.getLoggerName()),
    event.getLevel(),
    AidaUtils.sqlEscape(event.getMessage().toString()),
    event.getThrowableInformation()!=null ? event.getThrowableInformation().getThrowable() : null
  );

  return getLayout().format(clone);
}

回答by Chris Persichetti

To get around this problem logging to Oracle, you can use Oracle's quote operator.

要解决登录到 Oracle 的这个问题,您可以使用 Oracle 的引用运算符。

Wrap the quote operator around %m (i.e. q#'%m'#)

将引号运算符包裹在 %m 周围(即 q#'%m'#)

For example:

例如:

INSERT INTO log_messages ( log_level, message, log_date ) 
VALUES ( '%p', q#'%m'#, '%d{yyyy-MM-dd HH:mm:ss}' )

回答by Andrzej Doyle

As per the Javadocs, the offical JDBCAppender is quite limited, and in particular has no good way of dealing with this issue.

根据Javadocs,官方的 JDBCAppender 非常有限,尤其是没有很好的方法来处理这个问题。

One way around it is to use an alternative appender, such as this onewhich aims to be functionally compatible with the Log4J one except, you know, work.

解决它的一种方法是使用另一种附加程序,例如这个旨在与 Log4J 功能兼容的附加程序,除了工作之外。

回答by John Sobolewski

If you are using SQL server you can use the following

如果您使用的是 SQL 服务器,则可以使用以下内容

SET QUOTED_IDENTIFIER OFF;
INSERT INTO log_messages ( log_level, message, log_date ) VALUES ( "%p", ":%m", "%d{yyyy-MM-dd HH:mm:ss}" )'
SET QUOTED_IDENTIFIER OFF;

Which shifts the problem to double quotes. If you don't have double quotes in your messages this could solve the problem.

这将问题转移到双引号。如果您的消息中没有双引号,这可以解决问题。

回答by user2608613

For postgresql, use $$

对于 postgresql,使用 $$

Example: $$%m$$

示例:$$%m$$

回答by Rafael

Joao, sorry for being late, but here it is:

Joao,抱歉迟到了,但是这里是:

<appender name="DB" class="org.apache.log4j.db.DBAppender">                                                                                                             
                <connectionSource class="org.apache.log4j.db.DriverManagerConnectionSource">                                                                                       
                        <param name="driverClass" value="org.postgresql.Driver" />                                                                                                 
                        <param name="url" value="jdbc:postgresql://localhost/database" />                                                                                      
                        <param name="user" value="user" />                                                                                                                          
                        <param name="password" value="password" />                                                                                                                 
                </connectionSource>                                                                                                                                                
                <layout class="org.apache.log4j.PatternLayout">                                                                                                                    
                        <param name="ConversionPattern" value="%d %-5p [%t] %c - %m%n" />                                                                                          
                </layout>                                                                                                                                                          
        </appender>

Hope it helps!

希望能帮助到你!