Как очистить сообщения журнала в Log4j, чтобы сохранить их в базе данных - PullRequest
4 голосов
/ 11 января 2010

Я пытаюсь сохранить сообщения журнала в центральной базе данных. Для этого я настроил следующий Appender в конфигурации xml log4j:

<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>

Это работает нормально, за исключением того, что некоторые сообщения содержат ', и затем происходит сбой приложения.

Есть ли простой способ сделать это?

Ответы [ 9 ]

6 голосов
/ 11 января 2010

Я бы предложил создать собственный appender и переопределить методы flushBuffer и execute, чтобы вы могли экранировать свои строки или использовать PreparedStatement:

public class MyJDBCAppender extends JDBCAppender {

}

Чтобы объяснить, почему вам нужно переопределить flushBuffer - аппендер помещает LogEvent объекты в буфер, который затем сбрасывается в сторону цели (в данном случае, базы данных). Здесь метод flushBuffer использует getLogStatement и (через execute) нормальный Statement. Вы можете полностью заменить это поведение. Посмотрите текущий исходный код

Затем зарегистрируйте свой аппендант вместо JDBCAppender.

3 голосов
/ 19 января 2011

Я решил это следующим образом:

Скопирован исходный код JDBCAppender с именем ACMEJDBCAppender

переопределяет метод getLogStatement(LoggingEvent event), клонируя старое событие и предоставляя новому экранированное сообщение.

Не самое чистое решение с точки зрения 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);
}
3 голосов
/ 11 января 2010

Взгляните на этот неофициальный Log4J JDBCAppender , который решает эту проблему и распространяется под лицензией Apache 2.0. Приведем его характеристики в сравнении с org.apache.log4j.jdbc.JDBCAppender:

  • Вход в (реляционную) базу данных
  • Гибкая обработка соединений (пока не поддерживает DataSource)
  • Гибкие команды sql для фактического ведения журнала
  • Поддерживаемые подготовленные операторы и хранимые процедуры (J2SDK 1.4+)
  • Включение регистрации сообщений со специальными символами, такими как '(одиночный цитата) и, (запятая)
  • Гибкая структура таблицы и столбца
  • Гибкая генерация идентификатора
  • Допускается несколько приложений PatternLayout; в одном или нескольких Столбцы
  • Поддерживает J2SDK 1.3, 1.4 и 1.5
  • Поддерживает Log4j 1.2.9 и текущую разработку

Или, и вы должны серьезно рассмотреть эту опцию, переключиться с log4j на его преемника, logback (это то, где происходит), который имеет DBAppender, который использует PreparedStatement (см. sources ), которые могут использовать источник данных JNDI, пул соединений (это большой плюс) и т. д. Для получения дополнительной информации об этом приложении см. онлайн-руководство http://logback.qos.ch/manual/appenders.html#DBAppender

3 голосов
/ 11 января 2010

Я не знаком с log4j или JDBC, но знаю, что JDBC поддерживает подготовленные операторы. Возможно, есть способ использовать это с JDBCAppender

1 голос
/ 21 сентября 2011

Чтобы обойти эту проблему при регистрации в Oracle, вы можете использовать оператор цитаты Oracle.

Оператор кавычек обернуть вокруг% m (т.е. q # '% m' #)

Например:

INSERT INTO log_messages ( log_level, message, log_date ) 
VALUES ( '%p', q#'%m'#, '%d{yyyy-MM-dd HH:mm:ss}' )
1 голос
/ 11 января 2010

Согласно Javadocs , официальный JDBCAppender весьма ограничен и, в частности, не имеет хорошего способа решения этой проблемы.

Одним из способов решения этой проблемы является использование альтернативного приложенияНапример, этот , который нацелен на функциональную совместимость с Log4J, кроме работы.

0 голосов
/ 08 октября 2016

Для postgresql используйте $$

Пример: $$% m $$

0 голосов
/ 15 декабря 2014

Если вы используете сервер 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;

Что переносит проблему в двойные кавычки. Если в ваших сообщениях нет двойных кавычек, это может решить проблему.

0 голосов
/ 25 августа 2010

Жуан, извините за опоздание, но вот оно:

<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>

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...