软件打log的一些心得(非常好,必须学习)

打log的原则:

1. 异常分支或错误处理一定要打log

2. 重大操作时一定要打log,下面打log场景会讲述

log格式的原则:

1. 时间戳必须有,最好能够精确到微秒。精确到秒的时间戳,相信很多人都熟悉,这能够确认问题的时间和系统uptime的对比,能够进一步还原问题的场景。至于到微秒,在多线程程序下,如果进程停止响应,可以从日志时间看是否死锁。

一般格式:

[2017-01-09 12:16:30.541]

2.打log位置的文件名和代码行数。这个不用说,用于定位问题根源。其实最重要是防止扯皮。因为程序员大多喜欢copy-paste,如果你不加文件名和行数,某程序员copy了你的代码,修改了点,出错了,到时候把你拉下水。

一般格式:

[2017-01-09 12:16:30.541][network.c:541]

3. 有进程id。有些log机制在进程重启时,不会重新生成一个日志文件,而是直接在同一个日志文件后面添加日志。或者,有时候同一程序的多个进程同时运行,可能也会写入到同一个日志文件。

一般格式:

[2017-01-09 12:16:30.541][network.c:541][pid=15529]

4.有线程id。在多线程程序,如果不加线程id,很难追溯程序的行为

一般格式:

[2017-01-09 12:16:30.541][network.c:541][pid=15529][thread=0x12345]

5.有日志的级别。日志是反映问题的,有不同紧急程序的问题,自然有不同的日志级别。一般采用Error,Warning,Info,Debug。定义不同级别,也可以方便在日志查找问题来源。

一般格式:

[2017-01-09 12:16:30.541][network.c:541][pid=15529][thread=0x12345][Error]

打log的场景:

1. 申请内存时,失败的话,要把申请大小打印出来。以前我申请内存失败也是简单地打印:

[2017-01-09 12:16:30.541][network.c:541][pid=15529][thread=0x12345][Error]Failed to allocate memory

后来在重构时遇到一个问题:进程跑的时间一久,大概一天多,别的程序向它发消息都会收到失败响应,在日志里就是一大堆内存失败的消息"Failed to allocate memory"。用"free"命令来看,物理内存还有好几G空闲,而用“top”命令来看,该进程也只是占700M内存。当时我就怀疑是不是内存碎片导致。于是我把申请内存的大小也打印出来,就收到一堆这样的

[2017-01-09 12:16:30.541][network.c:541][pid=15529][thread=0x12345][Error]Failed to allocate memory of size 65536
[2017-01-09 12:16:30.588][network.c:541][pid=15529][thread=0x12345][Error]Failed to allocate memory of size 1048576

当时就看那些代码引用的数据结构,最小也有64K,大的16M都有,基本一个结构包括很多个大数组。当时就把那些数组全改为指针,再进一步申请,代码繁琐了,但这种问题再也不会出现。再看bug系统,原来这个问题存在很多,在其它程序也存在,当时都找不到根因,只是用过一段时间重启进程来解决


2. 函数参数非空判断时,要打印日志。原因不说,看对比:

之前

if ( ( pInfo == NULL ) || ( pHandler == NULL ) ) 
{
    log( ERROR, "invalid arguments" );
}

之后

if ( ( pInfo == NULL ) || ( pHandler == NULL ) ) 
{
    log( ERROR, "invalid arguments:(pInfo, pHandler )=(%p,%p)", 
            pInfo, pHandler );
}

3. 加载和卸载模块,无论是正常还是异常情况都要打印。毕竟这些操作大多都是一次性操作。对性能影响不大。

[2017-01-09 12:16:30.588][modules.c:54][pid=15529][thread=0x12345][Error]Failed to load module libftp.so, error=module already loaded

4. 操作文件目录时,失败要把文件名和错误码打印出来。如

[2017-01-09 12:16:30.588][config.c:120][pid=15529][thread=0x12345][Error]Failed to open file conf/ftp.xml, errno=(13:Permission denied)

假设这个错误导致进程初始化失败,且环境在客户那边,维护人员就可以确认并自己解决这个问题。

5. 操作socket时,把IP,端口号或路径名(Unix socket )和错误码打印出来。如

[2017-01-09 12:16:30.588][network.c:541][pid=15529][thread=0x12345][Error]Failed to connect to host (10.17.128.10:9981), errno=(111:Connection refused)

假设在客户环境出错,维护人员可以根据日志来确认10.17.128.10这台机器是否在线,是否开启了相应的服务,或者服务是开启了,可能只是端口配置错了(这种情况是扯皮最多的)

6. 操作数据库时,把相应操作的IP,端口,库,用户名,sql语句和错误打印出来。如

[2017-01-09 12:16:30.588][dbmgr.c:781][pid=15529][thread=0x12345][Error]user tiger failed to operate in host (10.17.128.10:3365) with db test, sql="select * from users", error="no table users exists"

在客户环境下,维护人员可以通过命令行来验证这些问题,来确定问题。可能有人会考虑安全性,毕竟在日志中把IP,端口,库,用户名都暴露出来了,这样好像不妥。但如果是从事过通信行业的网上问题维护,就知道,可维护性比这种细节的安全性还要重要。

7. 创建新进程时,需要把程序名,参数和错误码打印出来。如

[2017-01-09 12:16:30.588][process.c:154][pid=15529][thread=0x12345][Error]failed to execute program "iptables -L", errno=(2:No such file or directory)

往往在客户环境,由于运维人员水平参差不齐,可能误操作或漏操作,导致文件缺失或权限出错,这种错误在公司的模拟环境根本不会出现。如果日志够详细,能够减少很多工作量。


8. 解析文件时,需要把文件名,字段,行号打印出来。如

[2017-01-09 12:16:30.588][config.c:120][pid=15529][thread=0x12345][Error]Failed to parse file conf/ftp.xml, line:20, tag <host> is not closed

结语:上面的原则,基本是每一条是血的教训。以前在H时见得太多因为日志不全导致的麻烦,前方的客户经理不断向客户恳求宽限时间,维护人员不断地在客户环境找出蛛丝马迹,后方领导也不断地调配资源来跟踪问题,后方测试人员不断地测试,尝试问题复现,后方开发人员就不断地看代码。在Z也见过因为日志不全,导致被客户罚钱次数过多,整个产品都亏损了。像@帝都铁匠说的“感觉学会log,程序就算入门了”。

嵌入式软件打log的一些心得 以前在H时见得太多因为日志不全导致的麻烦,前方的客户经理不断向客户恳求宽限时间,维护人员不断地在客户环境找出蛛丝马迹,后方领导也不断地调配资源来跟踪问题,后方测试人员不断地测试,尝试问题复现,后方开发人员就不断地看代码。因为程序员大多喜欢copy-paste,如果你不加文件名和行数,某程序员copy了你的代码,修改了点,出错了,到时候把你拉下水。日志是反映问题的,有不同紧急程序的问题,自然有不同的日志级别。6、操作数据库时,把相应操作的IP,端口,库,用户名,sql语句和错误打印出来。... 阅读详情

相关推荐

Python高级语法——log/日志事件——学习心得笔记

Python高级语法——log——学习心得笔记 参考博客:Python之日志处理-logging模块(https://www.cnblogs.com/yyds/p/6901864.html) 1. 日志相关概念 日志的级别 不同用户关注不同的程序信息 日志的级别如下,从低到高 DEBUG INFO NOTICE WARNING ERROR CRITICAL ALERT EMERGENCY ...

Python美丽星球--微信(Felixzfb) 733

软件打log的一些心得

本文适用范围:Linux系统 使用语言:C/C++ 打log的原则: 1. 异常分支或错误处理一定要打log 2. 重大操作时一定要打log,下面打log场景会讲述 log格式的原则: 1. 时间戳必须有,最好能够精确到微秒。精确到秒的时间戳,相信很多人都熟悉,这能够确认问题的时间和系统uptime的对比,能够进一步还原问题的场景。至于到微秒,在多线程程序下,如果进程停止响应,可

梦想从这里开始 3330

PostgreSQL的学习心得和知识总结(一百五十七)|新的 COPY 选项 LOG_VERBOSITY

新的 COPY 选项 LOG_VERBOSITY

孤傲小二~阿沐的博客 1566

打印日志会不会影响性能?怎么办?

刚开始做开发的时候就有一个疑问, 我们开发一般为了调试方便都会给自己的业务代码加上一些日志, 那么问题来了, 打印这么多日志不会影响性能吗?这个肯定是必然的, 毕竟需要计算机分出一些性能来打印日志的, 但一般要求不苛刻的场景可以忽略这个问题前面说了一般情况下日志影响的性能是可以忽略的, 既然有一般那肯定就有不一般的情况, 今天来了解一下如何减少日志对性能的影响。

梧桐树的博客 1429

最好用的LOG工具

这是我至今为止用过的最好用的LOG工具,可以查看LOG,可以提取LOG,先保存到网络,以后使用的时候直接获取。本软件只供学习使用。

保姆级教程:手把手教你为裕泰微YT8521 PHY芯片编写Linux设备树(DTS)节点与驱动

本文提供了一份详细的保姆级教程,手把手教你为裕泰微YT8521 PHY芯片编写Linux设备树(DTS)节点与驱动。从基础配置到RGMII接口的特殊设置,再到驱动开发的关键步骤和调试技巧,帮助开发者快速掌握PHY芯片的移植与开发。

weixin_33734785的博客 333

为什么要打日志?怎么打日志?打什么日志?

公司的项目不会有e.printStackTrace();这种代码的存在。因为这打印出来的错误信息没有日期、等级等等,分析起来不方便。

sekever的博客 1138

OCR开发车架号识别vin码识别系统

一、vin码识别车架号识别系统简介   vin码识别车架号识别系统,结合VIN码主机厂数据库及自身多年文字识别经验,针对机动车配置参数等信息的查询及采集业务推出的一款VIN码自动识别产品。   车架号识别vin码识别,主要应用在智能手机IOS与Android两个平台中。前端扫描查询模式,无需联网,只需扫描汽车前挡风玻璃右下角的VIN玛(车架号),即可轻松识别出车辆产地、品牌、车

OCR13512721355的博客 1433

如何打一手好Log

  如果项目上过线的话,那你一定知道Log是多么重要。   为什么说Log重要呢?因为上线项目不允许你调试,你只能通过Log来分析问题。这时打一手好Log的重要性绝不亚于写一手好代码。项目出问题时,你要能拿出Log证明自己负责的部分没有问题,如果是自己的问题,要从Log里快速找出错误原因。如果没有从Log里找出错误原因,那一定是一件很悲催的事情,特别是在bug不容易重现的情况下。那简直...

dianling0264的博客 413

深入剖析:NAND Flash与SD NAND(贴片式SD卡)存储扇区分配表架构差异与优化策略

本文深入探讨了NAND Flash与SD NAND(贴片式SD卡)在存储技术中的架构差异及其优化策略。NAND Flash作为非易失性存储器,依赖主控芯片进行坏块管理和磨损均衡,而SD NAND则通过内置控制器和标准文件系统(如FAT)简化了存储管理。两者在写入性能、容量扩展和可靠性方面各有优劣,NAND Flash需通过磨损均衡和写入合并优化性能,而SD NAND则通过高容量和高速传输提升效率。文章为嵌入式系统开发者和硬件工程师提供了关于如何根据需求选择并优化存储介质的参考。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1238

保姆级教程:在Zynq UltraScale+ EV系列FPGA上,用VCU IP核搞定4K60帧H265视频解码与HDMI2.0输出

本文提供在Zynq UltraScale+ EV系列FPGA上使用VCU IP核实现4K60帧H265视频解码与HDMI2.0输出的全流程指南。从开发环境准备、Vivado工程配置到PetaLinux系统定制,详细解析硬件选型、IP核参数设置及性能优化技巧,帮助开发者快速构建高效视频处理系统。

weixin_30800987的博客 432

总结‘’

林天宇 17.19.12   第三天总结  我今天把生日贺卡,加法计算器,和计算机存款本息,还有C++的基本要素都跟着视频学了一遍。知道了 1.这计算器 还有 存款本息软件是怎么一步步的优化设计的,并且知道了怎么用。 2.有了很多数学函数的使用 pow sin exp log' 的用法。  明日目标:因为今天看的有点多,所以明天主要是复习,重新敲一遍。

qq_40621619的博客 165

蓝桥杯嵌入式(基础教程)STM32G431RBT6——创建工程以及点灯

首先选择正确的芯片类型:STM32G431RBT6工程的创建主要有配置时钟以及烧录的方式。在配置好之后需要对时钟进行配置,由于蓝桥杯的外部晶振是24MHz因此需要对时钟树进行相应的配置。第一步先点击时钟配置之后就可以对时钟进行相应的配置了最后一步,需要对工程起一个名字,并且要选择KEIL做为其相应的软件之后再需要再生成代码那里进行相应的控制。当然这样根据生成的工程不能直接使用会有一个报错,所以需要添加一个启动文件。这个启动文件可以在官方的LCD文件夹下复制到自己的工程中。

m0_74051113的博客 1093

《软件工程实务》学习心得

随着软件工程领域的快速发展,新的技术和方法不断涌现。课程中可以适当增加对一些前沿技术,如人工智能在软件工程中的应用、敏捷开发的最新实践等内容的介绍,使学生能够跟上行业发展的步伐。《软件工程实务》课程是我大学学习生涯中非常重要的一门课程。通过这门课程的学习,我不仅掌握了扎实的软件工程知识和技能,还在实践中锻炼了自己的团队协作能力和问题解决能力。这门课程为我今后从事软件开发工作奠定了坚实的基础。在未来的学习和工作中,我将继续运用所学的软件工程知识,不断提升自己的专业素养,为软件开发领域贡献自己的一份力量。

2403_88307691的博客 958

第一讲:halcon模板匹配捆绑测量矩形检测芯片针脚

使用halcon模板匹配捆绑测量矩形,检测位置发生变换的芯片针脚缺陷。

uiopmn1的博客 2995

树莓派 RP2350B 开发环境搭建

本文介绍了树莓派RP2350B开发环境的搭建过程。

张一西的博客 286

软件工程课程心得

记得第一个小组项目中,我们直接跳过了详细的需求分析阶段,结果在开发过程中不断遇到需求变更,导致代码结构频繁调整。这门课程为我打开了软件工程的大门,让我认识到编程只是软件开发的冰山一角。随着课程的深入,我逐渐认识到软件工程是一个系统化的过程,而编码只是其中的一个环节。通过实际项目,我深刻体会到好的提交习惯对团队协作的重要性。通过编写测试代码,我养成了先思考边界条件和异常场景的习惯,这显著提高了代码质量。

gljs1的博客 1169

用miniconda建立PyTorch、Keras、TensorFlow三个环境

如果还没有安装Miniconda,请从[Miniconda官网](https://docs.conda.io/en/latest/miniconda.html)下载合适的版本并进行安装。如果遇到问题,可以通过编辑`~/.condarc`文件来临时禁用某个源,或者通过`conda config --remove channels`命令来移除配置的镜像源。要切换到不同的环境,先使用`conda deactivate`命令退出当前环境,再用`conda activate 环境名称`命令激活另一个环境。

数字人生 2464

Java Web开发与软件部署测试学习心得

图9:完整的软件开发生命周期关键收获:🏗️ 分层架构是复杂系统的基石🧪 测试覆盖率≠质量,但能显著降低风险🐳 容器化解决了"在我机器上能跑"的问题⚡ CI/CD加速了交付周期需要改进:微服务监控体系混沌工程实践云原生技术深度附录:学习资源推荐Spring官方文档Docker最佳实践《测试驱动开发》Jenkins用户手册。

weixin_66976644的博客 590

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Android开发基础——Log

常规使用 Android的日志工具Log(import android.util.Log;)一共为我们提供了5个方法(优先级依次升高)来供我们打印日志,当然他们有不同的重载,按需使用。 Log.v() 对应的级别为verbose,是Android日志级别最低的一种。用于打印开发调试中的一些详细信息,最为琐碎、意义最小的日志,包含诸如方法名,变量值之类的信息,仅在开发中使用,不可在发布产品中输出。 Log.d() 对应级别为debug,比verbose高一级。开发中经常选择输出此种级别的日志,用于打印一些调

GeofferySun的专栏 1409

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

python第一周心得

这里写自定义目录标题Python 简介1.Python环境搭建(windows环境)欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UM...

qq_40800872的博客 2万+

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

学习Spring boot 的一些心得

如果项目需要与数据库进行交互或者处理数据对象,那么需要定义相应的实体类。实体类通常对应数据库中的表,其成员变量表示表中的列。例如,定义一个名为User@Entity@Id// 省略构造函数、getter和setter方法。

jiangke84的博客 734

spring Boot学习心得

通过学习 Spring Boot 的入门课程,我深刻体会到了它所带来的简洁高效的开发体验。同时,Spring Boot 的测试支持也非常强大,能够轻松进行单元测试和集成测试,保证了代码的质量。学习 Spring Boot 让我对微服务架构有了更深入的理解,为未来的项目开发提供了更多的选择。每一课的学习都让我对 Spring Boot 的理解更加深入,同时也激发了我持续学习的动力。我相信,在未来的开发工作中,Spring Boot 将成为我的得力工具,帮助我构建出更加优秀的应用。

SS_dujiadaoban的博客 1790

《软件工程实务》学后心得

通过这门课程,我实现了:✅ 从"会写代码"到"会做工程"的转变✅ 建立起完整的软件质量意识✅ 掌握团队协作的核心方法论未来计划继续深入学习软件架构设计,并考取软考高级资格证书。

2401_85969455的博客 288

【阅读心得】CNN 学习log

目标:最快了解CNN的原理,看懂matlab 的CNN代码。cnn原理:1)http://www.moonshile.com/post/juan-ji-shen-jing-wang-luo-quan-mian-jie-xi#toc_0

你好tesseract的专栏 865
上一篇: SpringMVC拦截器返回值不能自定义的解决办法
下一篇: 软件打log的一些心得(非常好,必须学习)
bbbbln
博客等级 码龄11年 14粉丝 59原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值