我正在使用 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/