Log4j FileAppender recreating deleted files

后端 未结 5 1730
悲哀的现实
悲哀的现实 2021-01-03 07:08

I am using Log4j as logging framework in a project I am working on. I have the following situation: Log4j is configured to write the logs into a log file. At some point, thi

相关标签:
5条回答
  • 2021-01-03 07:13

    Try This one. I do not have a Linux machine right now, so I'm not sure if it can resolve the performance issue.

    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.");
                    }
                }
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-03 07:19

    I went through the source code of log4j. When a FileAppender/RollingFileAppender is initialized, a FileOutputStream instance is created pointing to the File. A new FileDescriptor object is created to represent this file connection. This is the reason, the other solutions like Monitoring the file through Cron and Creating the File in append method by overriding didn't work for me, because a new file descriptor is assigned to the new file. Log4j Writer still points to the old FileDescriptor.

    The solution was to check if the file is present and if not call the activeOptions method present in FileAppender Class.

    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();
            }
        }
    }
    

    Finally add this to the log4j.properties file:

    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
    

    Note: I have tested this for log4j 1.2.17

    0 讨论(0)
  • 2021-01-03 07:20

    Make sure you can declare this line in your log4j file

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

    If you already declared it, you log file can delete or replace as you like. Then you rerun your program and new log file is created in this path.

    0 讨论(0)
  • 2021-01-03 07:25

    Try This Class

    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.");
                }
            }
        }
    }
    

    Also edit the log4j config file

    log4j.appender.R=wodong.test.LastFileAppender
    
    0 讨论(0)
  • 2021-01-03 07:36

    I study the source of log4j and find log4j can't create new log file, it just print the error message to system.err when the log file was deleted

        /** 
         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;  
      }  
    

    I think there are two workaround

    1. create another cron thread to monitor the log file
    2. add judge in getLog or getInstance (singleton), check the log file does exist, if not then init log4j
    0 讨论(0)
提交回复
热议问题