Log4j 的 BurstFilter 肯定会帮助您防止磁盘被填满。请记住对其进行配置,使其尽可能应用于有限的代码部分,否则您将过滤掉您可能想要保留的消息(也就是说,不要在 appender 上使用它,而是在特定的 logger 上使用它你在你的代码中隔离)。
我曾经编写了一个简单的实用程序类,它包装了一个记录器并根据给定 Duration 内的 n 条消息进行过滤。我在我的大部分警告和错误日志中都使用了它的实例,以防止我遇到像你一样的问题。它非常适合我的情况,特别是因为它更容易快速适应不同的情况。
类似:
...
public DurationThrottledLogger(Logger logger, Duration throttleDuration, int maxMessagesInPeriod) {
...
}
public void info(String msg) {
getMsgAddendumIfNotThrottled().ifPresent(addendum->logger.info(msg + addendum));
}
private synchronized Optional<String> getMsgAddendumIfNotThrottled() {
LocalDateTime now = LocalDateTime.now();
String msgAddendum;
if (throttleDuration.compareTo(Duration.between(lastInvocationTime, now)) <= 0) {
// last one was sent longer than throttleDuration ago - send it and reset everything
if (throttledInDurationCount == 0) {
msgAddendum = " [will throttle future msgs within throttle period]";
} else {
msgAddendum = String.format(" [previously throttled %d msgs received before %s]",
throttledInDurationCount, lastInvocationTime.plus(throttleDuration).format(formatter));
}
totalMessageCount++;
throttledInDurationCount = 0;
numMessagesSentInCurrentPeriod = 1;
lastInvocationTime = now;
return Optional.of(msgAddendum);
} else if (numMessagesSentInCurrentPeriod < maxMessagesInPeriod) {
msgAddendum = String.format(" [message %d of %d within throttle period]", numMessagesSentInCurrentPeriod + 1, maxMessagesInPeriod);
// within throttle period, but haven't sent max messages yet - send it
totalMessageCount++;
numMessagesSentInCurrentPeriod++;
return Optional.of(msgAddendum);
} else {
// throttle it
totalMessageCount++;
throttledInDurationCount++;
return emptyOptional;
}
}
不幸的是,我是从旧版本的代码中提取的,但要点就在那里。我写了一堆我主要使用的静态工厂方法,因为它们让我可以编写一行代码来为该日志消息创建其中一个:
} catch (IOException e) {
DurationThrottledLogger.error(logger, Duration.ofSeconds(1), "Received IO Exception. Exiting current reader loop iteration.", e);
}
这在您的情况下可能不会那么重要;对我们来说,我们使用的是一个动力不足的 graylog 实例,我们可以很容易地处理它。