简体   繁体   中英

Log4j2 DefaultRolloverStrategy Configuration deletes log files but not empty folders

I'm using log4j2 for my app logs, I'm using XML and the configuration below is for the logs. I am storing logs in folders named after the current date. Every day a new folder is created with a name say '2018-11-15' and logs are stored into it. The code deletes the log files according to the size and age but does not delete the empty folders(2018-11-15) after these files are deleted from the folder.

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Properties>
    <Property name="baseDir">logs</Property>
  </Properties>
  <Appenders>
    <RollingFile name="RollingFile" fileName="${baseDir}/app.log"
          filePattern="${baseDir}/$${date:yyyy-MM}/app-%d{yyyy-MM-dd-HH}-%i.log.gz">
      <PatternLayout pattern="%d %p %c{1.} [%t] %m%n" />
      <Policies>
        <TimeBasedTriggeringPolicy />
        <SizeBasedTriggeringPolicy size="250 MB"/>
      </Policies>
      <DefaultRolloverStrategy max="100">
        <!--
        Nested conditions: the inner condition is only evaluated on files
        for which the outer conditions are true.
        -->
        <Delete basePath="${baseDir}" maxDepth="2">
          <IfFileName glob="*/app-*.log.gz">
            <IfLastModified age="30d">
              <IfAny>
                <IfAccumulatedFileSize exceeds="100 GB" />
                <IfAccumulatedFileCount exceeds="10" />
              </IfAny>
            </IfLastModified>
          </IfFileName>
        </Delete>
      </DefaultRolloverStrategy>
    </RollingFile>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="RollingFile"/>
    </Root>
  </Loggers>
</Configuration>

How do I delete the folders once all the files inside it are deleted? Thanx!

You don't have a build in option in log4j2 for deleting empty folders. You can check this StackOverflow answer , and this log4j2 issues discussion .

I would say the easiest way to handle this is to run a cron regardless to the log4j configuration. I use crontab .

By default, Delete action will not delete folder, even if the folder is empty. If you want to delete folder according to the size and age, you can use Script to do this, see official doc for help: http://logging.apache.org/log4j/2.x/manual/appenders.html#ScriptCondition

Just return folders you want to delete from the script.

I had the same problem/ customer requirement and solved it like this:

<RollingRandomAccessFile name="ROLLING_TEXT_FILE_APPENDER" fileName="${sys:ehr.logDir}/ehr.log"
                             filePattern="${sys:ehr.logDir}/$${date:yyyy-MM}/ehr-%d{yyyy-MM-dd-HH}-%i.log.gz">
        <PatternLayout pattern="%d %p [%t(%T)] %c{-3} - %m%n" />
        <Policies>
            <SizeBasedTriggeringPolicy size="50MB"/>
            <TimeBasedTriggeringPolicy />
        </Policies>
        <DefaultRolloverStrategy>
            <Delete basePath="${sys:ehr.logDir}" maxDepth="2">
                <IfFileName glob="*/ehr-*.log.gz" />
                <IfLastModified age="30d" />
            </Delete>
            <Delete basePath="${sys:ehr.logDir}" maxDepth="2">
                <ScriptCondition>
                    <Script name="GroovyCondition" language="groovy"><![CDATA[
                        import java.nio.file.*
                        import java.nio.file.attribute.BasicFileAttributes;
                        import org.apache.logging.log4j.core.appender.rolling.action.PathWithAttributes;

                        List<PathWithAttributes> result = new ArrayList<PathWithAttributes>();

                        statusLogger.trace 'SCRIPT: Checking for empty folders in base path: ' + basePath
                        Files.list(basePath).filter(p -> p.toFile().isDirectory()).forEach(p ->{
                            statusLogger.trace 'SCRIPT: Testing if folder is empty: ' + p
                            try(DirectoryStream<Path> dirStream = Files.newDirectoryStream(p)) {
                                // is directory empty?
                                if (!dirStream.iterator().hasNext()) {
                                    statusLogger.trace 'SCRIPT: Returning empty folder for deletion: ' + p
                                    BasicFileAttributes attributes = Files.readAttributes(p, BasicFileAttributes.class);
                                    result.add(new PathWithAttributes(p, attributes));
                                }
                            }
                        })

                        return result;
                    ]]>
                    </Script>
                </ScriptCondition>
            </Delete>
        </DefaultRolloverStrategy>
    </RollingRandomAccessFile>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM