基于行和时间的日志打印
有个需求,是要按照行和日期进行日志切割,后来根据官网介绍和百度查阅,找到了一种方法,稍加修改,记录一下,
首先声明用到的包如下,不同的包继承的类会不同<properties>
<slf4j.api.version>1.7.14</slf4j.api.version>
<log4j.slf4j.impl.version>2.5</log4j.slf4j.impl.version>
<log4j.core.version>2.5</log4j.core.version>
</properties>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.api.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j.slf4j.impl.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.core.version}</version>
</dependency>
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.appender.rolling.RollingFileManager;
import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy;
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.PluginFactory;
import org.apache.logging.log4j.status.StatusLogger;
/**
* 自定义基于行和时间的滚动日志
*
*/
@Plugin(name = "LineBasedTriggeringPolicy", category = "Core", printObject = true)
public class LineBasedTriggeringPolicy implements TriggeringPolicy {
/**
* Allow subclasses access to the status logger without creating another
* instance.
*/
protected static final StatusLogger LOGGER = StatusLogger.getLogger();
/**
* Rollover threshold size in bytes.
*/
private static final long MAX_LINE_SIZE = 10 * 1024 * 2; // let 20k line
private static final int MAX_ELAPSE_TIME = 24 * 60 * 60 * 1000; // 1day
private final long maxLineSize;
private final int maxElapsedTime; // in ms
private int counter = 0;
private long lastUpdateTime = System.currentTimeMillis();
/**
* 是为了防止上次日志达不到滚动条件而停止服务后,重启后原日志不滚动而直接追加新日志,导致超过规定条件
*/
private AtomicInteger times = new AtomicInteger(1);
private RollingFileManager manager;
/**
* Constructs a new instance.
*/
protected LineBasedTriggeringPolicy() {
this.maxLineSize = MAX_LINE_SIZE;
maxElapsedTime = MAX_ELAPSE_TIME;
}
/**
* Constructs a new instance.
*
* @param maxFileSize rollover threshold size in bytes.
*/
protected LineBasedTriggeringPolicy(final long maxFileSize,
int maxElapsedTime) {
this.maxLineSize = maxFileSize;
this.maxElapsedTime = maxElapsedTime;
}
/**
* Create a LineBasedTriggeringPolicy.
*
* @param size The size of the file before rollover is required.
* @return A LineBasedTriggeringPolicy.
*/
@PluginFactory
public static LineBasedTriggeringPolicy createPolicy(@PluginAttribute("size")
final String size, @PluginAttribute("maxElapsedTime")
final String maxElapsedTime) {
final long maxSize = size == null ? MAX_LINE_SIZE : Integer
.valueOf(size);
int time = maxElapsedTime == null ? MAX_ELAPSE_TIME / 1000 : Integer
.valueOf(maxElapsedTime);
return new LineBasedTriggeringPolicy(maxSize, time * 1000);
}
/**
* Initialize the TriggeringPolicy.
*
* @param manager The RollingFileManager.
*/
public void initialize(final RollingFileManager manager) {
this.manager = manager;
}
/**
* Returns true if a rollover should occur.
*
* @param event A reference to the currently event.
* @return true if a rollover should take place, false otherwise.
*/
public boolean isTriggeringEvent(final LogEvent event) {
if (counter == 0 && times.intValue() == 1) {
times.incrementAndGet();
return true;
}
counter++;
int cur = counter;
boolean ret = cur >= maxLineSize;
if (!ret) {
long time = System.currentTimeMillis() - lastUpdateTime;
if (time > maxElapsedTime) {
ret = true;
}
}
if (ret) {
counter = 0;
lastUpdateTime = System.currentTimeMillis();
}
return ret;
}
@Override
public String toString() {
return "LineBasedTriggeringPolicy(size=" + maxLineSize + ")";
}
}
测试方法
public class TestLog {
private static final Logger logger = LoggerFactory.getLogger("com.xxx.test.log");
public static void main(String[] args) throws InterruptedException {
while (true) {
logger.info("TestLogController");
Thread.sleep(1000);
}
}
}
log4j2.xml配置
<?xml version="1.0" encoding="utf-8"?>
<Configuration monitorInterval="30" packages="com.xxx.controller">
<Appenders>
<Console name="console" target="SYSTEM_OUT">
<PatternLayout
pattern="%m%n"/>
</Console>
<RollingFile name="testLog" fileName="D:/testLog.log"
filePattern="D:/$${date:yyyy-MM}/$${date:yyyy-MM-dd}/testLog-%d{yyyy-MM-dd-HH-mm-ss}-%i.log.bak">
<PatternLayout pattern="%m%n"/>
<Policies>
<LineBasedTriggeringPolicy size="10" maxElapsedTime="10"/>
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="console"/>
</Root>
<Logger name="com.xxx.test.log" level="info" additivity="false">
<AppenderRef ref="testLog"/>
</Logger>
</Loggers>
</Configuration>
启动后我们可以看到能正常输出日志,且每次都是10条
然后暂停,将休眠时间改为2S
我们可以看到重启后第一次日志只有7条就回滚了,这就说明代码加了第一次输出日志就回滚生效了
我们可以看到将休眠时间改为2S后就一直每次都是5条了