Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在log4j中自动折叠重复日志输出_Java_Logging_Log4j_Log4j2 - Fatal编程技术网

Java 如何在log4j中自动折叠重复日志输出

Java 如何在log4j中自动折叠重复日志输出,java,logging,log4j,log4j2,Java,Logging,Log4j,Log4j2,每隔一段时间,服务器或数据库错误就会在服务器日志文件中导致数千个相同的堆栈跟踪。今天的错误/堆栈跟踪可能与一个月前不同。但它会导致日志文件完全旋转,我不再了解以前发生的事情。(或者,我不想耗尽磁盘空间,因为我目前无法控制的原因,磁盘空间是有限的——我将单独解决这个问题)。无论如何,我不需要同一堆栈跟踪的数千个副本——只要十几个就足够了 如果我能让log4j/log4j2/另一个系统自动折叠重复错误,这样它们就不会填满日志文件,我会很高兴。例如,来自同一位置的10或100个异常的阈值可能会触发lo

每隔一段时间,服务器或数据库错误就会在服务器日志文件中导致数千个相同的堆栈跟踪。今天的错误/堆栈跟踪可能与一个月前不同。但它会导致日志文件完全旋转,我不再了解以前发生的事情。(或者,我不想耗尽磁盘空间,因为我目前无法控制的原因,磁盘空间是有限的——我将单独解决这个问题)。无论如何,我不需要同一堆栈跟踪的数千个副本——只要十几个就足够了

如果我能让log4j/log4j2/另一个系统自动折叠重复错误,这样它们就不会填满日志文件,我会很高兴。例如,来自同一位置的10或100个异常的阈值可能会触发log4j开始计数,并等待它们停止出现,然后输出它们出现的次数的计数

有哪些预先制定的解决方案(最好是通过链接进行快速调查)?如果这是我应该自己实现的东西,那么什么是好的模式开始,我应该注意什么


谢谢

你想做什么就做什么?如果没有,请创建一个JILA问题的算法,将为您工作,而Log4J团队将很乐意考虑它。更好的是,如果你能提供一个补丁,它将更有可能被合并。

Log4j的BurstFilter肯定会帮助你防止填充磁盘。请记住对其进行配置,以使其在尽可能有限的代码段中应用,或者过滤掉可能要保留的消息(也就是说,不要在appender上使用它,而是在代码中隔离的特定记录器上使用它)

我曾经编写过一个简单的实用程序类,它包装了一个记录器,并根据给定持续时间内的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;
    }
}

在你的情况下,这可能没有那么重要;对于我们来说,我们使用的是一个动力不足的graylog实例,我们可以很容易地使用它。

您是否尝试过扩展日志文件的大小和/或数量?此外,您的问题的真正解决方案似乎是修复导致所有stacktraces的问题。@DwB,正如我在原始问题中提到的,我对VM磁盘大小没有太多的控制权(这一决定主要由我自己决定,目前正在单独讨论);对于您关于修复堆栈痕迹原因的建议的另一部分:是的,当然这是给定的,但我们并不是生活在一个理想的世界中;特别是当系统的集成点和依赖性超出了我的控制范围时,我不一定有时间去修复所有的事情。另外,正如我所说的——关键是在出现意外错误输出时保留日志。这看起来与我要查找的非常接近,尽管我想通过行号或方法名称进一步限制它(例如,仅过滤具有相同来源的类似消息)。不过,这是朝着正确方向迈出的一步。
} catch (IOException e) {
     DurationThrottledLogger.error(logger, Duration.ofSeconds(1), "Received IO Exception. Exiting current reader loop iteration.", e);
}