configuration - 在 log4j2 中,如何将 RollingFile 附加程序的 renameEmptyFiles 配置为 false?

标签 configuration log4j rename log4j2 rollingfileappender

我正在使用 log4j 2 和 RollingFile 附加程序:

<RollingFile name="mylog"
fileName="mylog.log"
filePattern="mylog.log.%d{yyyy-MM-dd}.log">
  <PatternLayout>
    <pattern>[%d] [%-5p] [%-8t] %F:%L %m%n</pattern>
  </PatternLayout>
  <Policies>
    <TimeBasedTriggeringPolicy interval="1"/>
  </Policies>
</RollingFile>

日志文件每天都会重命名。但是Javadoc of FileRenameAction class表示有一个选项 renameEmptyFiles 默认情况下为 false,因此如果一天的日志为空,它将删除它,而不是重命名它,将日期附加到文件名。由于我想拥有日志文件,即使它是空的,如何将其配置为 true?

最佳答案

我制作了一个提供所需功能的小插件。我只是扩展了 DefaultRolloverStrategy 并替换了从 rollover() 返回的 RolloverDescription 对象(因为它的所有字段都是 final) 。我从 DefaultRolloverStrategy 复制了静态 @PluginFactory 代码,因为 Log4j 2 插件系统需要它。

代码如下:

import java.util.zip.Deflater;

import org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy;
import org.apache.logging.log4j.core.appender.rolling.RollingFileManager;
import org.apache.logging.log4j.core.appender.rolling.RolloverDescription;
import org.apache.logging.log4j.core.appender.rolling.RolloverDescriptionImpl;
import org.apache.logging.log4j.core.appender.rolling.action.Action;
import org.apache.logging.log4j.core.appender.rolling.action.FileRenameAction;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.lookup.StrSubstitutor;
import org.apache.logging.log4j.core.util.Integers;

@Plugin( name = "KeepEmptyFilesRolloverStrategy", category = "Core", printObject = true )
public class KeepEmptyFilesRolloverStrategy extends DefaultRolloverStrategy
{
   private static final int MIN_WINDOW_SIZE = 1;
   private static final int DEFAULT_WINDOW_SIZE = 7;

   @PluginFactory
   public static KeepEmptyFilesRolloverStrategy createStrategy( @PluginAttribute( "max" ) final String max,
                                                                @PluginAttribute( "min" ) final String min,
                                                                @PluginAttribute( "fileIndex" ) final String fileIndex,
                                                                @PluginAttribute( "compressionLevel" ) final String compressionLevelStr,
                                                                @PluginElement( "Actions" ) final Action[] customActions,
                                                                @PluginAttribute( value = "stopCustomActionsOnError", defaultBoolean = true ) final boolean stopCustomActionsOnError,
                                                                @PluginConfiguration final Configuration config )
   {
      final boolean useMax = fileIndex == null ? true : fileIndex.equalsIgnoreCase( "max" );
      int minIndex = MIN_WINDOW_SIZE;
      if ( min != null )
      {
         minIndex = Integer.parseInt( min );
         if ( minIndex < 1 )
         {
            LOGGER.error( "Minimum window size too small. Limited to " + MIN_WINDOW_SIZE );
            minIndex = MIN_WINDOW_SIZE;
         }
      }
      int maxIndex = DEFAULT_WINDOW_SIZE;
      if ( max != null )
      {
         maxIndex = Integer.parseInt( max );
         if ( maxIndex < minIndex )
         {
            maxIndex = minIndex < DEFAULT_WINDOW_SIZE ? DEFAULT_WINDOW_SIZE : minIndex;
            LOGGER.error( "Maximum window size must be greater than the minimum windows size. Set to "
                          + maxIndex );
         }
      }
      final int compressionLevel = Integers.parseInt( compressionLevelStr, Deflater.DEFAULT_COMPRESSION );
      return new KeepEmptyFilesRolloverStrategy( minIndex,
                                                 maxIndex,
                                                 useMax,
                                                 compressionLevel,
                                                 config.getStrSubstitutor(),
                                                 customActions,
                                                 stopCustomActionsOnError );
   }

   protected KeepEmptyFilesRolloverStrategy( int minIndex,
                                             int maxIndex,
                                             boolean useMax,
                                             int compressionLevel,
                                             StrSubstitutor subst,
                                             Action[] customActions,
                                             boolean stopCustomActionsOnError )
   {
      super( minIndex, maxIndex, useMax, compressionLevel, subst, customActions, stopCustomActionsOnError );
   }

   @Override
   public RolloverDescription rollover( final RollingFileManager manager ) throws SecurityException
   {
      RolloverDescription oldResult = super.rollover( manager );

      // Fail fast (ClassCastException) if implementation of DefaultRolloverStrategy 
      // ever changes and uses a different Action type. 
      FileRenameAction oldRenameAction = (FileRenameAction) oldResult.getSynchronous();
      FileRenameAction newRenameAction = new FileRenameAction( oldRenameAction.getSource(),
                                                               oldRenameAction.getDestination(),
                                                               true );

      RolloverDescription newResult = new RolloverDescriptionImpl( oldResult.getActiveFileName(),
                                                                   oldResult.getAppend(),
                                                                   newRenameAction,
                                                                   oldResult.getAsynchronous() );

      return newResult;
   }
}

要使用此类,只需在 Log4j 2 XML 配置中引用它即可,例如像这样:

<RollingFile name="RollingFile" fileName="/usr/local/glassfish4.1-webprofile/glassfish/domains/domain1/logs/server.log" filePattern="/usr/local/glassfish4.1-webprofile/glassfish/domains/domain1/logs/server.%d{yyyyMMdd-HH:mm}.log">
  <KeepEmptyFilesRolloverStrategy/>
  <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
  <CronTriggeringPolicy schedule="0 * * * * ?"/>
</RollingFile>

实现的灵感来自 this相关答案。

顺便说一句,可能需要使用新的 CronTriggeringPolicy 来创建空日志文件,因为它使用单独的线程。从 SO 上的一些其他答案来看,只要 Appender 不写出任何内容,至少其他一些策略就无法对触发器使用react。

关于configuration - 在 log4j2 中,如何将 RollingFile 附加程序的 renameEmptyFiles 配置为 false?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32378201/

相关文章:

configuration - 与 pycharm 一起使用 odoo 的配置问题

spring - 在spring配置文件中设置资源

c# - WCF SSL 配置可能错误

java - 将日志记录添加到实用程序包

java - log4j 喜欢 jar 文件中的属性吗?

db2 - 如何在 sql DB2 中重命名表/移动到不同的模式?

python - 将模板文件复制到多个目录,根据目录查询模板文件重命名

java - 如何在 spring-boot 应用程序中从 YML 文件加载多个属性

java - 如何使用Java重命名目录中的所有文件?

log4j - 我怎么知道 Log4j 从哪里选择它的配置