Аппендер для Log4J

Я неоднократно натыкался на различные обертки для Log4J. Иногда это мотивировалось тем что вдруг мы решим использовать другой логгер или нужно «чтото свое»

В первом случае можно взять Jakarta Commons Logging который говорят и является оберткой поверх логгеров. Хотя по мне так вероятность замены логгера очень близка к нули и это лишь трата времени и забивание головы лишними мыслями «а вдруг?».

Во втором это совсем не причина отказа, т.к. Log4J прекрасно меняется под наши условия, нужно только доки прочитать повнимателней. Можно написать свой appender который куда угодно запишет.

Вот, например, могу показать как писать лог в базу. Хотя подобный аппендер есть в стандартной поставке, но он stack-trace не пишет. Попробуем это исправить:

public class DBLogAppender extends AppenderSkeleton {

    private String SQL = "insert into logs(time, location, message, trace, level) " +
            " values(?, ?, ?, ?, ?)";

    protected synchronized void append(LoggingEvent loggingEvent) {
        Connection conn = null;
        try {
            conn = getConnection();
            PreparedStatement query = conn.prepareStatement(SQL);
            query.setTimestamp(1, new Timestamp(loggingEvent.timeStamp));
            StringBuilder buf = new StringBuilder();
            //делаем удобочитаемую строчку для нахождения где у нас собсно вывалилось
            buf.append(loggingEvent.getLocationInformation().getClassName());
            buf.append(" ");
            buf.append(loggingEvent.getLocationInformation().getFileName());
            buf.append(":");
            buf.append(loggingEvent.getLocationInformation().getLineNumber());

            query.setString(2, buf.toString());

            query.setString(3, loggingEvent.getMessage().toString());

            //Делаем stack-trace
            if ( loggingEvent.getThrowableStrRep() != null
                 && loggingEvent.getThrowableStrRep().length > 0) {

                buf = new StringBuilder();
                for ( String line : loggingEvent.getThrowableStrRep() ) {
                    buf.append(line);
                    buf.append("\n");
                }

                query.setString(4, buf.toString());
            } else {
                query.setString(4, null);
            }

            query.setInt(5, loggingEvent.getLevel().toInt());

            query.executeUpdate();
            conn.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public boolean requiresLayout() {
        return false;
    }

    public void close() {
        try {
            getConnection().close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

метод getConnection () написать думаю будет несложно.

а потом в log4j.properties дописываем чтото типа того:

log4j.appender.db=com.mycompany.project.DBLogAppender
log4j.appender.db.url=jdbc:postgresql://localhost/mydatabase
log4j.appender.db.driver=org.postgresql.Driver
log4j.appender.db.user=loguser
log4j.appender.db.password=pasword

да, в саммом классе я не показал сеттеры и геттеры для url, driver, user и password, чтобы не загромождать пост. В общем таким вот образом можно передать параметры в класс, как String а дальше использовать, как в нашем случае для настройки коннекшена к базе.

  • http:// aefimov

    Полностью согласен. Только единицы пишут свои аппендеры к Log4J и больше не парятся с логированием и багрепортингом. Остальные начинают придумывать велосипеды.

    К единицам односится IntelliJ IDEA и пожалуй из известных мне — все.

  • Pingback: hello « Anduno’s Weblog

  • http:// Andrey P.Rybin

    Случайно нашел ваш блог, читаю. Хоть тема и старая, напишу.

    Сейчас с появлением slf4j.org от автора log4j вопрос с логированием полностью закрыт.

    slf4j.org + log4j

    или

    slf4j.org + logback.qos.ch

  • http:// Alno

    Другой вариант, использования slf4j: slf4j + logback.

    logback заявляется как последователь log4j, +добавляет какое-то количество новых фичей и вроде бы более расширяем.

  • http:// Жорик

    Проблема с гетером параметров. Как получит параметр из log4j.properties, например этот — log4j.appender.db.url=jdbc:postgresql://localhost/mydatabase?