【问题标题】:How to reduce logs size [closed]如何减小日志大小[关闭]
【发布时间】:2013-12-13 14:06:19
【问题描述】:

在我从事的每个项目中,总是存在日志文件变得过大的问题。 一个快速现成的解决方案是使用 Log4j RollingFileAppender 并设置允许的最大大小。 但是,在某些情况下,在有人手动干预之前,相同的异常会反复发生并很快达到最大大小。在那种情况下,由于滚动策略,您最终会丢失发生在异常之前的重要事件的信息。 有人可以建议解决此问题吗?

附:我能想到的是保存到目前为止发生的Exceptions 的缓存,这样当再次发生相同的异常时,我就不会记录大量的堆栈跟踪行。不过我认为这一定是一个众所周知的问题,我不想重新发明轮子。

【问题讨论】:

  • 什么样的异常?如果这是您可以解决或改进的问题,请考虑您可能正在尝试治疗症状而不是问题。您还可以考虑使用FileHandler 来使用轮换日志。您可以指定日志文件的数量及其最大大小,并在它们之间循环。此外,请考虑让您的代码按照@TimB 的建议定期压缩日志。
  • 因此问题不是要求提供站外资源、工具或库。答案指出了几种不需要其他工具的潜在解决方案。
  • @Gep 我也面临着类似的问题。你最后采用了什么方法?

标签: java logging log4j rollingfileappender


【解决方案1】:

有两个方向可以解决这个问题:系统端和开发端。从系统端(即在应用程序部署和运行之后)处理这个问题已经有几个答案。但是,我想谈谈开发方面。

我看到的一个非常常见的模式是在每个级别记录异常。我看到 UI 组件、EJB、连接器、线程、帮助类、pojo 等,等等,记录所有发生的异常。在许多情况下,无需费心检查日志级别。这具有您遇到的确切结果以及使调试和故障排除花费比必要更多的时间,因为必须筛选所有重复的错误。

我的建议是在代码中执行以下操作:

  • 思考。 并非每个异常都是致命的,而且在许多情况下实际上是无关紧要的(例如,IOException 来自流上的 close() 操作。)我不想说,“不要“不记录异常”,因为您当然不想错过任何问题,所以在最坏的情况下,将日志语句放在调试级别的条件检查中

    if(logger.isDebugEnabled()){
    // log exception
    }

  • 仅在顶层记录。我确信这会遇到一些负面影响,但我的感觉是,除非该类是应用程序或组件的顶层接口,或者异常不再被传递,那么应该记录异常。换句话说,如果异常被重新抛出、包装并抛出或声明为从方法中抛出,则不要在该级别记录它。

例如,第一种情况是导致日志语句过多的问题,因为调用者和任何被调用的对象都可能会记录异常或有关错误的某些语句。

public void something() throws IllegalStateException{
      try{
         // stuff that throws some exception
      }catch(SomeException e){
         logger.error(e); // <- NO because we're throwing one
         throw new IllegalStateException("Can't do stuff.",e);
      }
 }

既然要扔了,就不要记录了。

 public void something() throws IllegalStateException{
      try{
         // stuff that throws some exception
      }catch(SomeException e){
         // Whoever called Something should make the decision to log
         throw new IllegalStateException("Can't do stuff.",e);
      }
 }

但是,如果something 停止传播异常,它应该记录它。

 public void something(){
      try{
         // stuff that throws some exception
      }catch(SomeException e){
         if(logger.isLogLevelEnabled(Log.INFO)){
            logger.error(e);                      // DEFINITELY LOG! 
         }
      }
 }

【讨论】:

  • 非常有用的帖子,但它忽略了如何处理更常见的情况:应用程序堆栈中使用的无数库之一实际上并没有抛出异常;例如,当您使用 JEE 容器时会遇到挑战。除了最小化日志时刻之外,它还有助于为特定的包/库类微调日志过滤器,以过滤掉最终出现在那里的所有无用垃圾。
  • @Gimby 同意。好点。
  • 感谢 MadConan 和 Gimby。迄今为止对我来说最好的答案。
【解决方案2】:

使用“滚动文件附加器”达到指定大小后,使用 Log4J 功能压缩日志文件。一个 1MB 文件的 Zips 大约是 85KB。 为此,请根据大小指定要压缩的触发策略,并在滚动策略中指定 zip 文件。
如果您需要信息,请告诉我。

【讨论】:

  • 没有链接吗?
  • 这只是一个解决方案,而不是具体的答案。但是您可以通过谷歌搜索或在 stackoverflow 上找到使用 SizeBasedRollingPolicy 压缩日志文件 herehere 的示例。
【解决方案3】:

根据我的经验,日志记录是用来代替正确测试和调试代码的。程序员对自己说,“我不能确定这段代码是否有效,所以我会在其中添加日志消息,这样当它失败时,我可以使用日志消息找出问题所在。”

不要只是随意散布日志消息,而应将每条日志消息视为软件用户界面的一部分。 DBA、网站管理员或系统管理员的用户界面,但仍然是用户界面的一部分。每条消息都应该做一些有用的事情。该信息应该是对行动的刺激,或提供他们可以使用的信息。如果一条消息没有用,请不要记录它。

为每条消息指定适当的日志记录级别。如果消息没有描述实际问题,并且没有提供通常有用的状态信息,则该消息可能仅对调试有用,因此将其标记为 DEBUG 或 TRACING 消息。您通常的 Log4J 配置根本不应该写入这些消息。仅在调试问题时更改配置以编写它们。

您提到这些消息是由于经常发生的异常引起的。并非所有异常都表明程序存在错误,甚至程序运行存在问题。您应该记录所有表明程序中存在错误的异常,并记录它们的堆栈跟踪。在许多情况下,这几乎就是您找出错误原因所需的全部内容。如果您担心的异常是由于错误引起的,那么您关注的是错误的问题:您应该修复错误。如果异常并不表示程序中存在错误,则不应为其记录堆栈跟踪。堆栈跟踪仅对尝试调试问题的程序员有用。如果异常根本不表示问题,则根本不需要记录它。

【讨论】:

    【解决方案4】:

    购买更大的硬盘并设置批处理以定期自动压缩旧日志。

    (Zip 会检测重复的异常模式并非常有效地对其进行压缩)。

    【讨论】:

    • 感谢 Tim B。但是硬盘已经很大了:但是它被许多服务共享,每个服务都产生它自己的日志。我正在寻找该问题的软件解决方案。
    • 它实际上可以用 Java 完成,我在一个 android 项目中使用了一个类,它可以压缩日志,甚至可以将新的日志文件添加到 zip 文件中。不反对您的回答,只是提供不同的方法。
    【解决方案5】:

    如果达到最大大小,使用该策略,追加到新的日志文件。并像每天一样运行调度程序来擦除旧的日志文件

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多