首页 > 代码库 > 关于日志记录的总结

关于日志记录的总结

  前段时间,公司的一个项目,需要做很多的数据接口和同步程序,于是就遇到了日志记录的问题,何时记录,如何记录,哪些要记哪些不用记等问题。针对日志记录的问题,经过一系列讨论,终于达成了统一的处理办法。解决了各个模块系统,不同的开发人员,日志记录不统一,随意的问题。今天终于抽出时间把这个问题总结并结合网络上的资料,进行整理。

  为什么要记录日志

  记录日志是调试程序,监视程序运行的一种重要的方式,主要有两个目的:bug的及时发现和定位,显示程序运行状态。正确详细的日志记录能够快速的定位问题。同样,通过查看日志,可以看出程序正在做什么,是不是按预期的设计在执行,所以记录下程序的运行状态是必要的。

  哪些地方需要记日志

  1. 调用或封装外部程序或接口
    程序中对外部系统与模块的依赖调用前后都应该记下日志,方便接口调试。出问题时也可以很快查出是哪里出的问题

    LOG.debug("Calling external system:" + parameters);
    Object result = null;
    try {
      result = callRemoteSystem(params);
      LOG.debug("Called successfully. result is " + result);
    } catch (Exception e) {
      LOG.warn("Failed at calling xxx system . exception : " + e);
    }

  2.对重要对象或变量被修改,要以INFO记录修改前的信息和修改后的状态。
    程序中重要的状态信息的变化应该记录下来,方便查问题时还原现场,推断程序运行过程

    boolean isRunning;
    isRunning = true;
    LOG.info("System is running");
    //...
    isRunning = false;
    LOG.info("System was interrupted by " + Thread.currentThread().getName());

  3.系统入口与出口:
    系统的入口和出口,重要方法或模块的执行。记录它的输入与输出,方便定位。

  4.业务异常或者重要的业务处理:
    任何业务异常都应该记下来,还有系统中一些重要的业务,比如结算等业务,也最好能记录下来。

  5.非预期执行:
    为程序在“有可能”执行到的地方打印日志。如果我想删除一个文件,结果返回成功。但事实上,那个文件在你想删除之前就不存在了。最终结果是一致的,但程序得让我们知道这种情况,要查清为什么文件在删除之前就已经不存在

    int myValue = http://www.mamicode.com/xxxx;
    int absResult = Math.abs(myValue);
    if (absResult < 0) {
      LOG.info("Original int " + myValue + "has nagetive abs " + absResult);
    }
  6.很少出现的else情况:
    代码中,一定要有完整的if else,如果else 里面没有要执行的,记录日志,这样避免else吞掉你的请求,或是返回给你难以理解的结果。

    Object result = null;
    if (running) {
      result = xxx;
    } else {
      result = yyy;
      LOG.debug("System does not running, we change the final result");
    }

  7. 批量数据的执行进度:

    LOG.debug("current progress: " + (currentPos * 100 / totalAmount) + "%");

  日志记录的方式

  1. 日志信息应该包含记录程序运行时间和错误发生的时间.

  2. 日志信息清晰准确有意义
    日志应该是清晰准确的: 当看到日志的时,就能准确的知道错误是因为连接池取不到连接导致的问题。

    Connection connection = ConnectionFactory.getConnection();
    if (connection == null) {
      LOG.warn("System initialized unsuccessfully");
    }
  3. 记录错误的位置
    代码中,一定要记录下错误所在的文件名和函数名(必须能区分开重载函数),有行数最好。

  4. 区分日志级别
    在程序中Log进行分级是很重要的,通常可以分为6 级:TRACE<DEBUG<INFO<WARN<ERROR<FATAL。
DEBUG用来输出调试信息,一般是在程序中不是非常重要的地方;INFO代表一些比较重要的信息,比如程序初始化完毕,ERROR一般指程序本身引起的,可以恢复的错误;FATAL一般指程序所依赖的环境出现错误,使的程序不恢复。其中常用的是DEBUG和 ERROR。

  5. 信息详细准确
一定要记录下完整准确的信息,否则还不如记录,因为错误的信息可能会误导开发人员。所以最简单的办法就是记录完整的stack trace.

  6. 最好能给log带上上下文
    没有相应的上下文的log,不过是噪音,它们不会对调试过程中有意义的数值或是空间起作用。
    Transaction failed 这样的log信息比没有记录更让人抓狂。