【ArchSummit架构师峰会】探讨数据与人工智能相互驱动的关系>>> 了解详情
写点什么

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

  • 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:1918420

评论

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

优雅设计之美:实现Vue应用程序的时尚布局

快乐非自愿限量之名

Vue 前端 开发

免费下载高质量PPT模板,这12个优质模板网站值得推荐!

彭宏豪95

效率工具 PPT 在线白板 PPT模板 办公软件

Substance 3D Designer最新图文安装教程 附Ds激活补丁

Rose

【网易智企】《MCtalk·CEO对话》正式上线!首期对话高成资本

网易云信

人工智能 SaaS AIGC

苹果电脑占用内存多?DaisyDisk for Mac快速释放存储空间

南屿

mac软件下载 DaisyDisk Mac版下载 清理磁盘软件 Mac磁盘优化

语音聊天室APP运营第一天:打造交互式社交体验

山东布谷科技胡月

语音直播 语音聊天室开发 语聊平台 语音派对房

最好用的延时摄影制作软件LRTimelapse Pro 5下载安装 带LRTimelapse汉化补丁

南屿

Mac软件 延迟摄影 LRTimelapse Pro 5破解版 LRTimelapse中文 电影抗闪烁

谷歌推广该选择SEO还是Ads?谷歌技巧分享及实战

九凌网络

SRM源码供应商招标采购管理系统

金陵老街

源码 Vue Java' spring-boot SRM系统

全新加密叙事,以Solmash为代表 LaunchPad 平台如何为用户赋能?

EOSdreamer111

微前端无界机制浅析

快乐非自愿限量之名

前端 前端开发 前端框架

【SpringBoot实战专题】「开发实战系列」全方位攻克你的技术盲区之Spring定义Jackson转换Null的方法和实现案例

洛神灬殇

Java spring springboot 后端技术、 2024年第八篇文章

你真的会用 npx 吗❓❓❓

EquatorCoco

前端 开发 Node npx

Finder增强神器XtraFinder for Mac中文注册版

南屿

Mac破解软件 访达 Finder增强 XtraFinder Mac版 XtraFinder注册码

Head First Java(第二版·中文版)PDF

程序员李木子

【思考-衡量成员在团队的价值】

Geek_b2fe7a

团队 日常思考

十分钟教你在 k8s 中部署一个前后端应用

不在线第一只蜗牛

Kubernetes 容器 云原生 k8s

有没有可以拖拉拽生成一个低代码平台?

这我可不懂

软件开发 低代码 拖拽表单 JNPF

Effective Java中文版(第3版)PDF

程序员李木子

indesign2024打开后进不了页面

Rose

2024-01-13:用go语言,现在有一个打怪类型的游戏,这个游戏是这样的,你有n个技能, 每一个技能会有一个伤害, 同时若怪物小于等于一定的血量,则该技能可能造成双倍伤害, 每一个技能最多只能释放

福大大架构师每日一题

福大大架构师每日一题

索尼电视投屏软件就用Mirror for Sony TV for mac

南屿

Mac软件 索尼电视 投屏

浅谈6种流行的API架构风格

EquatorCoco

架构 开发 API

授权的艺术

俞凡

管理

安全易用的广告拦截器:AdGuard for Mac 中文激活版 兼容M1/M2

南屿

AdGuard Mac版 Mac广告拦截工具 苹果软件下载站

一文解析低代码平台

高端章鱼哥

低代码开发 应用开发 JNPF

【思考-责任与决策】

Geek_b2fe7a

日常思考

半小时实现GPT纯血鸿蒙版

不在线第一只蜗牛

人工智能 AI技术 鸿蒙开发 GPT

全新加密叙事,以Solmash为代表的 LaunchPad 平台如何为用户赋能?

股市老人

PlistEdit Pro for Mac(Plist编辑器) v1.9.7免激活版

南屿

Mac用户最爱的应用:Magnet 窗口辅助管理工具 分屏工作更高效!

南屿

mac窗口管理工具 Mac分屏 magnet pro 中文版 magnet pro 破解版

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