Log4j: события появляются в неправильном лог-файле

Чтобы иметь возможность регистрировать и отслеживать некоторые события, я добавил класс LoggingHandler в свой проект Java. Внутри этого класса я использую два разных экземпляра log4j logger - один для регистрации события и один для отслеживания события в разных файлах. Блок инициализации класса выглядит следующим образом:

public void initialize()
{
    System.out.print("starting logging server ...");

    // create logger instances
    logLogger = Logger.getLogger("log");
    traceLogger = Logger.getLogger("trace");

    // create pattern layout
    String conversionPattern = "%c{2} %d{ABSOLUTE} %r %p %m%n";
    try
    {
        patternLayout = new PatternLayout();
        patternLayout.setConversionPattern(conversionPattern);
    }
    catch (Exception e)
    {
        System.out.println("error: could not create logger layout pattern");
        System.out.println(e);
        System.exit(1);
    }

    // add pattern to file appender
    try
    {
        logFileAppender = new FileAppender(patternLayout, logFilename, false);
        traceFileAppender = new FileAppender(patternLayout, traceFilename, false);
    }
    catch (IOException e)
    {
        System.out.println("error: could not add logger layout pattern to corresponding appender");
        System.out.println(e);
        System.exit(1);
    }

    // add appenders to loggers
    logLogger.addAppender(logFileAppender);
    traceLogger.addAppender(traceFileAppender);

    // set logger level
    logLogger.setLevel(Level.INFO);
    traceLogger.setLevel(Level.INFO);

    // start logging server
    loggingServer = new LoggingServer(logLogger, traceLogger, serverPort, this);
    loggingServer.start();

    System.out.println(" done");
}

Чтобы убедиться, что только один поток использует функциональность экземпляра регистратора одновременно, каждый метод ведения журнала / трассировки вызывает метод ведения журнала.info() внутри синхронизированного блока. Один пример выглядит так:

    public void logMessage(String message)
{
    synchronized (logLogger)
    {
        if (logLogger.isInfoEnabled() && logFileAppender != null)
        {
            logLogger.info(instanceName + ": " + message);
        }
    }
} 

Если я смотрю на файлы журнала, я вижу, что иногда событие появляется в неправильном файле. Один пример:

trace 10:41:30,773 11080 INFO masterControl(192.168.2.21): string broadcast message was  pushed from 1267093 to vehicle 1055293 (slaveControl 1)
trace 10:41:30,784 11091 INFO masterControl(192.168.2.21): string broadcast message was pushed from 1156513 to vehicle 1105792 (slaveControl 1)
trace 10:41:30,796 11103 INFO masterControl(192.168.2.21): string broadcast message was pushed from 1104306 to vehicle 1055293 (slaveControl 1)
trace 10:41:30,808 11115 INFO masterControl(192.168.2.21): vehicle 1327879 was pushed to slave control 1
10:41:30,808 11115 INFO masterControl(192.168.2.21): string broadcast message was pushed from 1101572 to vehicle 106741 (slaveControl 1)
trace 10:41:30,820 11127 INFO masterControl(192.168.2.21): string broadcast message was pushed from 1055293 to vehicle 1104306 (slaveControl 1)

Я думаю, что проблема возникает каждый раз, когда два события происходят одновременно (здесь: 10:41:30,808). У кого-нибудь есть идеи, как решить мою проблему? Я уже пытался добавить sleep() после вызова метода, но это не помогло...

BR,

Markus

Редактировать:

logtrace  11:16:07,75511:16:07,755  1129711297  INFOINFO  masterControl(192.168.2.21): string broadcast message was pushed from 1291400 to vehicle 1138272 (slaveControl 1)masterControl(192.168.2.21): vehicle 1333770 was added to slave control 1

или же

log 11:16:08,562 12104 INFO 11:16:08,562 masterControl(192.168.2.21): string broadcast message was pushed from 117772 to vehicle 1217744 (slaveControl 1)

12104 INFO masterControl(192.168.2.21): автомобиль 1169775 переведен в режим подчиненного управления 1

Изменить 2:

Кажется, что проблема возникает только в том случае, если методы ведения журнала вызываются из потока RMI (мой клиент / сервер обменивается информацией с использованием соединений RMI). ...

Изменить 3:

Я решил проблему самостоятельно: кажется, что log4j НЕ полностью сохраняет потоки. После синхронизации всех методов log / trace с использованием отдельного объекта все работает нормально. Может быть, библиотека записывает сообщения в небезопасный буфер перед записью их в файл?

3 ответа

Этому вопросу 4 года, но я только что столкнулся с этой же проблемой в 2013 году, и, думаю, я исправил ее, создав новый шаблон PatternLayout для каждого Appender. Надеюсь, что это поможет кому-то еще с той же проблемой в будущем.

Может ли быть так, что метод инициализации вызывается более одного раза? При каждом вызове добавляются два новых приложения, которые записывают в тот же файл, что и существующие приложения.

Вам не нужно синхронизироваться на вашем регистраторе, а на выходном потоке.

Если вы используете log4j, вывод должен быть правильно синхронизирован. Единственный способ получить то, что вы видите, состоит в том, что два потока пишут в один и тот же файл одновременно.

Возможно ли, что вы настроили два приложения с одним и тем же выходным файлом? Не делай этого; у каждого аппендера должно быть свое собственное имя файла.

Если вы на 100% уверены, что каждый аппендер записывает в отдельный файл, остается только один вариант - вы иногда используете неправильный регистратор.

Другие вопросы по тегам