硬核干货——《中小企业 AI 实战指南》免费下载! 了解详情
写点什么

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

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

评论

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

中国商飞与宁德时代携手,技术创新引领航空新能源

科技汇

JavaScript中如何遍历对象?

电子尖叫食人鱼

JavaScript 前端

Java的SPI机制详解

京东科技开发者

链游新纪元——链游平台开发引领游戏新潮流!

区块链软件开发推广运营

交易所开发 dapp开发 链游开发 公链开发 代币开发

IT小伙伴要知道的-IT运维堡垒机相关知识

行云管家

堡垒机 IT运维

Agentic时代,我们需要什么样的数据工程(一)

MatrixOrigin

CAD如何测立面?详细教程来了

在路上

cad

深入拆解MCP架构:手把手搭建智能体通信桥梁

聚客AI学院

MCP MCP协议 mcpserver MCP Server MCP头号玩家

订单初版—分布式订单系统的简要设计文档

不在线第一只蜗牛

架构 订单

Awesome Mac 精选资源合集

qife122

macos 命令行工具

失明十年后,他在这里找到当大侠的感觉

脑极体

AI

脑机接口一百年

脑极体

AI

三维图纸描述太费劲?直接上「批注」,协作更顺畅!

在路上

cad

中选名单出炉|18位学生入选开源之夏KubeEdge课题,欢迎加入!

华为云原生团队

云计算 容器 云原生

人工智能丨这七大核心AI框架竟然都支持MCP

测试人

人工智能 软件测试

流批一体的“奥卡姆剃刀”:Apache Cloudberry 增量物化视图应用解析

酷克数据HashData

中国商飞与宁德时代跨界,共护投资者权益

科技汇

京东携手HarmonyOS SDK首发家电AR高精摆放功能

HarmonyOS SDK

HarmonyOS HarmonyOS NEXT HarmonyOS SDK应用服务

解读 OP 治理第八季:看 Superchain 生态下的链间协同与治理

NFT Research

blockchain Web3.0 Optimism

中国商飞与宁德时代战备合作,市场影响深远

科技汇

一张表就是一个智能业务系统,钉钉全新发布“AI表格”

ToB行业头条

Claude Code 免费羊毛快薅

白大米

Claude cursor

京东零售基于国产芯片的AI引擎技术

京东科技开发者

MyEMS开源能源管理系统核心代码解读010

开源能源管理系统

开源 代码 能源管理 开源能源管理系统

MyEMS开源能源管理系统核心代码解读012

开源能源管理系统

开源 能源管理 代码解读

企业和个人基于业务知识和代码库增强的大模型生成代码实践

京东科技开发者

CleanMyMac一直提示输入密码怎么办?

阿拉灯神丁

MacBook Mac 软件 CleanMyMac X

区块链合约交易所开发攻略

区块链软件开发推广运营

交易所开发 dapp开发 链游开发 公链开发 代币开发

MyEMS开源能源管理系统核心代码解读011

开源能源管理系统

开源 能源管理

PPT字体替换全攻略!这2个使用技巧办公必备

职场工具箱

人工智能 AI PPT AIGC AI生成PPT

百度阮瑜:百度大模型应用赋能产业智变|2025全球数字经济大会

百度Geek说

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