转载/日志记录的作用和方法
最新推荐文章于 2024-08-11 21:19:45 发布
原创
最新推荐文章于 2024-08-11 21:19:45 发布
·
136 阅读
·
0
·
0
·
CC 4.0 BY-SA版权
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
日志
专栏收录该内容
6 篇文章
订阅专栏
本文介绍了如何通过良好的日志记录来高效地定位程序问题。包括记录外部调用、状态变化、系统入口与出口等,同时提供了示例代码,并强调了避免混淆信息、记错位置与级别的常见误区。
程序中记录日志一般有两个目的:Troubleshooting和显示程序运行状态。好的日志记录方式可以提供我们足够多定位问题的依据。日志记录大家都会认为简单,但如何通过日志可以高效定位问题并不是简单的事情。这里列举下面三个方面的内容,辅以代码示例,总结如何写好日志,希望对他人有所启发和帮助:怎样记日志可以方便Troubleshooting程序运行状态可以记哪些应该避免怎样的日志方式怎样记日志可以方便Troubleshooting?1. 对外部的调用封装程序中对外部系统与模块的依赖调用前后都记下日志,方便接口调试。出问题时也可以很快理清是哪块的问题1. LOG.debug("Calling external system:" + parameters); 2. Object result = null; 3. try { 4. result = callRemoteSystem(params); 5. LOG.debug("Called successfully. result is " + result); 6. } catch (Exception e) { 7. LOG.warn("Failed at calling xxx system . exception : " + e); 8. }2.状态变化程序中重要的状态信息的变化应该记录下来,方便查问题时还原现场,推断程序运行过程1. boolean isRunning; 2. 3. isRunning = true; 4. LOG.info("System is running"); 5. 6. //... 7. 8. isRunning = false; 9. LOG.info("System was interrupted by " + Thread.currentThread().getName());3.系统入口与出口:这个粒度可以是重要方法级或模块级。记录它的输入与输出,方便定位1. void execute(Object input) { 2. LOG.debug("Invoke parames : " + input); 3. Object result = null; 4. 5. //business logic6. 7. LOG.debug("Method result : " + result); 8. }4.业务异常:任何业务异常都应该记下来:1. try { 2. //business logical 3. } catch (IOException e) { 4. LOG.warn("Description xxx" , e); 5. } catch (BusinessException e) { 6. LOG.warn("Let me know anything"); 7. } catch (Exception e) { 8. LOG.error("Description xxx", e); 9. } 10.5.非预期执行:为程序在“有可能”执行到的地方打印日志。如果我想删除一个文件,结果返回成功。但事实上,那个文件在你想删除之前就不存在了。最终结果是一致的,但程序得让我们知道这种情况,要查清为什么文件在删除之前就已经不存在1. int myValue = xxxx; 2. int absResult = Math.abs(myValue); 3. if (absResult < 0) { 4. LOG.info("Original int " + myValue + "has nagetive abs " + absResult); 5. }6.很少出现的else情况:else可能吞掉你的请求,或是赋予难以理解的最终结果1. Object result = null; 2. if (running) { 3. result = xxx; 4. } else { 5. result = yyy; 6. LOG.debug("System does not running, we change the final result"); 7. }程序运行状态可以记哪些?程序在运行时就像一个机器人,我们可以从它的日志看出它正在做什么,是不是按预期的设计在做,所以这些正常的运行状态是要有的。1. 程序运行时间:1. long startTime = System.currentTime(); 2. 3. // business logical 4. 5. LOG.info("execution cost : " + (System.currentTime() - startTime) + "ms"); 2. 大批量数据的执行进度: 1. LOG.debug("current progress: " + (currentPos * 100 / totalAmount) + "%");3.关键变量及正在做哪些重要的事情:执行关键的逻辑,做IO操作等等1. String getJVMPid() { 2. String pid = ""; 3. // Obtains JVM process ID 4. LOG.info("JVM pid is " + pid); 5. return pid; 6. } 7. 8. void invokeRemoteMethod(Object params) { 9. LOG.info("Calling remote method : " + params); 10. //Calling remote server 11. }应该避免怎样的日志方式?1. 混淆信息的Log日志应该是清晰准确的: 当看到日志的时候,你知道是因为连接池取不到连接导致的问题么?1. Connection connection = ConnectionFactory.getConnection(); 2. if (connection == null) { 3. LOG.warn("System initialized unsuccessfully"); 4. }2. 记错位置产品代码中,使用console记录日志,导致没有找到日志。 1. } catch (ConfigurationException e) { 2. e.printStackTrace(); 3. }3. 记错级别记错级别常常发生,常见的如:混淆代码错误和用户错误,如登录系统中,如果恶意登录,那系统内部会出现太多WARN,从而让管理员误以为是代码错误。可以反馈用户以错误,但是不要记录用户错误的行为,除非想达到控制的目的。1. LOG.warn("Failed to login by "+username+");4. 遗漏信息这里可能包含两种情况:(1)用户自己少写了信息,导致毫无参考价值;(2)用户调用log的方式导致丢失信息,如下例,没有stack trace. 1. } catch (Exception ex) { 2. log.error(ex); 3. }