Log4j FileAppender воссоздает удаленные файлы

Я использую Log4j в качестве основы для ведения журнала в проекте, над которым я работаю. У меня следующая ситуация: Log4j настроен на запись журналов в файл журнала. В какой-то момент этот файл журнала копируется в другое место назначения и удаляется. Каркас ведения журнала продолжает работать, но журналы не записываются в файл журнала, поскольку он удален. Есть ли способ сказать Log4j пересоздать файл и продолжать записывать журналы в файл журнала.

С наилучшими пожеланиями, Рашид

5 ответов

Решение

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

    /** 
     This method determines if there is a sense in attempting to append. 

     <p>It checks whether there is a set output target and also if 
     there is a set layout. If these checks fail, then the boolean 
     value <code>false</code> is returned. */  

  protected   boolean checkEntryConditions() {  
    if(this.closed) {  
      LogLog.warn("Not allowed to write to a closed appender.");  
      return false;  
    }  

    if(this.qw == null) {  
      errorHandler.error("No output stream or file set for the appender named ["+  
            name+"].");  
      return false;  
    }  

    if(this.layout == null) {  
      errorHandler.error("No layout set for the appender named ["+ name+"].");  
      return false;  
    }  
    return true;  
  }  

Я думаю, что есть два обходных пути

  1. создайте другой поток cron для мониторинга файла журнала
  2. добавьте судью в getLog или getInstance (singleton), проверьте, существует ли файл журнала, если нет, то init log4j

Я прошел через исходный код log4j, Когда FileAppender/RollingFileAppender инициализируется, FileOutputStream создается экземпляр, указывающий на файл. Новый FileDescriptor Объект создан для представления этого файлового соединения. По этой причине другие решения, такие как "Мониторинг файла через Cron" и "Создание файла в методе добавления путем переопределения", у меня не работали, потому что новый файловый дескриптор был назначен новому файлу. Log4j Writer по-прежнему указывает на старый FileDescriptor.

Решением было проверить, присутствует ли файл, а если нет, вызвать метод activeOptions в классе FileAppender.

package org.apache.log4j;

import java.io.File;
import org.apache.log4j.spi.LoggingEvent;

public class ModifiedRollingFileAppender extends RollingFileAppender {

    @Override 
    public void append(LoggingEvent event) {
        checkLogFileExist();
        super.append(event);
    }

    private void checkLogFileExist(){
        File logFile = new File(super.fileName);
        if (!logFile.exists()) {
            this.activateOptions();
        }
    }
}

Наконец добавьте это в файл log4j.properties:

log4j.rootLogger=DEBUG, A1
log4j.appender.A1=org.apache.log4j.ModifiedRollingFileAppender
log4j.appender.A1.File=/path/to/file
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss,SSS} %p %c{1}: %m%n

//Skip the below lines for FileAppender
log4j.appender.A1.MaxFileSize=10MB
log4j.appender.A1.MaxBackupIndex=2

Примечание: я проверил это для log4j 1.2.17

Попробуйте этот класс

package wodong.test;
import java.io.File;
import java.io.IOException;

import org.apache.log4j.FileAppender;
import org.apache.log4j.spi.LoggingEvent;

public class LastFileAppender extends FileAppender {
    @Override
    public void append(LoggingEvent event) {
        checkLogFileExist();
        super.append(event);
    }
    private void checkLogFileExist(){
        File logFile = new File(super.fileName);
        if (!logFile.exists()) {
            try {
                logFile.createNewFile();
            } catch (IOException e) {
                System.out.println("Error while create new log file.");
            }
        }
    }
}

Также отредактируйте файл конфигурации log4j

log4j.appender.R=wodong.test.LastFileAppender

Убедитесь, что вы можете объявить эту строку в вашем файле log4j

    log4j.appender.rollingFile.File=D:/myapp/mylog.log

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

Попробуй это. У меня сейчас нет компьютера с Linux, поэтому я не уверен, что он сможет решить проблему с производительностью.

package wodong.test;
import java.io.File;
import java.io.IOException;

import org.apache.log4j.FileAppender;
import org.apache.log4j.spi.LoggingEvent;

public class LastFileAppender extends FileAppender {
    @Override
    public void append(LoggingEvent event) {

        checkLogFileExist();
        super.append(event);
    }

    private void checkLogFileExist() {
        if (qw == null) {
            File logFile = new File(super.fileName);
            if (!logFile.exists()) {
                try {
                    logFile.createNewFile();
                } catch (IOException e) {
                    System.out.println("Error while create new log file.");
                }
            }
        }
    }
}
Другие вопросы по тегам