50万奖金+官方证书,深圳国际金融科技大赛正式启动,点击报名 了解详情
写点什么

程序那些事:日志记录的作用和方法

  • 2012-11-06
  • 本文字数:2271 字

    阅读完需:约 7 分钟

程序中记录日志一般有两个目的: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 logic
6.
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. }

总结:

日志记录在程序员日常编程实践中必须面对的事情,本文针对这个话题谈了下自己的体会,希望读者能有所收益。多有不足,请多包涵。

参考文献

http://www.infoq.com/cn/articles/10-java-questions-easy-to-ignore

作者介绍

冶秀刚, 平台工程师,从事分布式收集与存储系统的研究与开发,爱好读书,喜欢涉猎各类能长见识的内容


给 InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ )或者腾讯微博( @InfoQ )关注我们,并与我们的编辑和其他读者朋友交流。

2012-11-06 00:1919475

评论

发布
暂无评论
发现更多内容

东莞理工大学-第四届“火焰杯”软件测试高校就业选拔赛颁奖典礼

测吧(北京)科技有限公司

测试

Python读取Ansible playbooks返回信息

不在线第一只蜗牛

Python sql 表单设计

高效聚合 | AIRIOT智慧虚拟电厂管理解决方案

AIRIOT

智慧电厂 智慧工厂 数字化工厂

SourceTree 4.1.5(Git客户端工具)

Geek_幻墨成诗

sourcetree SourceTree Mac

车家互联再获重磅突破,小度携手极越开启智能生活无限畅联新体验

新消费日报

创业有术,烧钱有道丨华为云为初创企业指明发展之路

平平无奇爱好科技

如何运用AppLink平台中的数据连接器组件

谷云科技RestCloud

MySQL APPlink

河南工业大学在第三届“火焰杯”软件测试开发选拔赛中 取得佳绩

测吧(北京)科技有限公司

测试

厦门理工学院五名学子获第四届“火焰杯”软件测试开发选拔赛全国奖项

测吧(北京)科技有限公司

测试

数字化红利进入“下半场” ,华为云耀云服务器L实例全力构建中小企业磁力场

平平无奇爱好科技

开启数字化转型新纪元,华为云引领轻量应用服务器创新

平平无奇爱好科技

华为云耀云服务器L实例助力企业行稳致远

平平无奇爱好科技

韩山师范学院-获第四届“火焰杯”软件测试开发选拔赛全国奖项

测吧(北京)科技有限公司

测试

Web前端开发技术:图像与多媒体文件

不在线第一只蜗牛

前端 Web 图像处理

软件测试/人工智能|探究 LangChain 核心模块:PromptsModelsParsers

霍格沃兹测试开发学社

网安学院举办第三届“火焰杯”软件测试高校就业选拔赛颁奖典礼

测吧(北京)科技有限公司

测试

轻量应用服务器为何是小程序开发“黄金搭档”?华为云给出完美答案

平平无奇爱好科技

凭实力碾压友商!中小企业网站建设盲选华为云这款轻量应用服务器

平平无奇爱好科技

性能优化的一般策略及方法

不在线第一只蜗牛

性能优化 优化 优化策略

通过亚马逊云科技云存储服务探索云原生应用的威力

亚马逊云科技 (Amazon Web Services)

云原生 S3 ebs 云存储服务 EFS

GPTs大受欢迎但问题多,企服软件厂商的AI Agent更被B端客户器重

王吉伟频道

AI Agent AI智能体 RPA Agent GPTs RPA智能体

快速渡过新手期!华为云服务器让小程序开发的试错成本更低

平平无奇爱好科技

初创企业太“烧钱”?华为云轻量应用服务器激活创业新思维

平平无奇爱好科技

软件测试/人工智能|什么是LangChain,这篇文章告诉你

霍格沃兹测试开发学社

区块链开发:链接未来的技术之桥

区块链软件开发推广运营

dapp开发 区块链开发 链游开发 NFT开发 公链开发

如何获取item_question_answer-淘宝评论问答列表api接口

技术冰糖葫芦

AI 模型编译器 API 文档 COMSOL Multiphysics

长春工业大学-在2023年全国大学生“火焰杯”软件测试大赛中喜获佳绩

测吧(北京)科技有限公司

测试

助力企业实现更简单的数据库管理,ATOMDB 与 TDengine 完成兼容性互认

TDengine

tdengine 时序数据库

软件测试/人工智能|LangChain Memory模块:开启语言数据的存储与回忆之旅

霍格沃兹测试开发学社

程序那些事:日志记录的作用和方法_Java_冶秀刚_InfoQ精选文章