转自:https://blog.csdn.net/weixin_43063753/article/details/82899395

程序为什么要写日志?
#为了能够在程序在运行过程中记录错误,方便维护,和调试,减少维护成本

为什么需要写日志
首先我们要树立一个观点,那就是“不是为了记录日志而记录日志,日志也不是随意记的”。要实现能够只通过日志文件还原整个程序执行的过程,达到能透明地看到程序里执行情况,每个线程每个过程到底执行到哪的目的。日志就像飞机的黑匣子一样,应当能够复原异常的整个现场乃至细节。

作为程序员,我相信吐槽写注释、写文档的段子已经见得很多了。然而在我看来,写日志的重要性完全不亚于前两者,甚至在很多时候,比前两者更为重要。

我们说“软件工程”,很多人只着眼了“软件”两个字,而忽视了“工程”。软件本身是为解决问题服务的,作为一项工程,我们不单要考虑软件本身的开发环节(注释、文档),还应当考虑软件的运营环节(日志)。世界上没有100%完美的事,不存在没有 bug 的软件系统,一旦软件上线,作为开发人员的我们,就不再能够接触到了,如果系统发生了异常,我们却又对系统运行的状态一无所知,那我们就完全没有办法解决问题。有时候重启一下应用,重启一下系统什么的,也能临时解决,但这只是掩耳盗铃,该来的还会再来,出现过的异常,还会在某一天再次出现。

这个时候对“日志”的需求便应运而生。通过日志,记录程序在运行过程中的细节,记录发生异常时的现场,我们便能像庖丁解牛一样,对运行中的应用了如指掌了。

什么时候写日志
所谓“麻雀虽小五脏俱全”,当我们在建构一个软件系统框架时,所谓的几层结构,所谓的基础模块(通用模块、工具模块、数据访问模块……),包括写日志的模块,这些方法都是不用思考,放之四海而皆准的东西,直接搭建/拼凑起来再说。

然后呢?我想很多人就开始闷头做功能了——我是指只写功能代码,完成实际的业务逻辑。在做业务功能的时候,由于现代IDE的调试功能很强大,可以一行一行调试,看到运行状态、变量状态等等,所以此时对日志的需求和功用是极度不敏感,觉得此时可有可无。但是一旦业务功能做完了,基于各种各样的理由,工期紧啊,已经完成功能了啊,就直接转测不再继续完善了。其结果是,功能的确完成了,但是搭建的日志模块却几乎没有使用。完成了整个系统,只有不痛不痒的两三行日志,大多都是在搭建框架时写的“应用启动了”,“应用停止了”一类。后面就不用说了,都说回头补设计文档,有多少人补了?都说回头补注释,有多少人补了?既然已经转测了,既然已经上线了,就更不会再回头去写日志了。

后来,可想而知,当生产环境除了问题,由于没有日志,到底出了什么异常,就两眼一抹黑,没人能知道了。终于,临时解决了问题,意识到日志的重要性之后,急急回头翻出代码来写日志,可是当时做业务的逻辑、思考、陷阱、注意事项等等,都忘记的差不多了,写日志也就只能像看陌生代码一样,看表面,“进入了XXX方法”,“插入数据库完成”,只能写这样的日志了。而在我看来,这样的日志是不够的,这也是我最反感的写日志的方式,完全是为了写而写——也是不足以还原故障现场的,这个后续再说。

说到此可能你应该也看出来的,什么时候写日志是最佳时机呢?那就是在开发功能代码时。可以说,日志本身也是属于功能代码的一部分,只不过业务功能是给最终客户的,而日志是给运维、开发等用的。此时写日志有一个巨大的好处,那就是因为你是一边在思考,一边在开发,那么此时业务流转、可能的异常都会考虑得很完善,写日志的过程,也是反复思考和校验逻辑的过程,也就自然而然地会在日志中体现更多的关键信息。

日志是写给谁看的
当然是给运维了啊,运维能够第一时间看到,比如日志中写端口被占用,马上改个端口就可以了!
当然是给开发了啊,每次系统发生了异常,运维人员不是直接把日志给开发人员一丢就了事了吗?
在我看来,不论是运维,还是开发,再广泛地讲,包括白盒测试,都是需要看日志的。日志对不同的人,都有不同的使用价值。运维通过日志了解到程序基本的安装、环境依赖、加载情况、运行态信息等等;开发通过日志还可以了解到程序对业务处理的信息,每个业务的流程、环节、现场状态等等;白盒测试也可以通过日志了解到程序要求的非功能特性等等。

日志里都要写什么
明确了“为什么要写日志”和“日志写给谁看的”了之后,要回答“日志里都要写什么”就容易得多了。我们需要从多个侧面来想这个问题。

考虑使用者
正如前文说,日志可能面向运维、面向开发等等不同身份的人群。因此日志的内容上,就要为不同的人写入其关切的入不同内容。

考虑业务
这里的“业务”可能不一定是最终用户的业务,也可能是中间态的业务逻辑。当业务处理出现问题时,到底是程序的bug造成,还是错误的数据造成,或者是硬件、网络等资源的问题造成,这些都应当能够从日志中分析得出来。

一段日志,应当能够对故障现场的每一个细节都能在大脑思维里复盘。同时,日志不单单像流水账一样记录程序的运行过程,每行日志还不应该是孤立的,还应当是一个有机的整体,是有上下文的,有头有尾的。比如下面这一段日志:

日志中记录了一些关键事件以及一些关键信息。比如什么时候侦测到了新消息,有几个Handler可以去处理,每个Handler对应了哪个线程,每个线程对应在处理那种消息;有了某个处理过程的开始,就应当有对应的结束,如果涉及到多线程,还应当能够区分两行同样的日志,对应的不同线程和不同业务单据等等。而不仅仅是“侦测到消息”,“开始处理”,“处理完毕”这种简单的记录。

考虑运营
对于业务,一般我们需要后续的分析和运营,日志在这方面也有起到较大作用,因此这部分日志应当考虑以结构化、规范化的方式来记录,从而方便后续对日志进行自动化分析。

考虑生命周期
那么日志是越详细越好,记录得越多越好吗?是。也不是。

每一个软件系统都是有一定的生命周期的。刚测试上线的软件,一般最不稳定,最容易出现各种这样那样的问题,此时日志应当详细些。而长期运行了很久的软件,经过了时间、业务的大量考验,该出现的bug也已经修复得差不多了,几乎不会再出现什么问题,日志应当少一些。

怎么实现呢?很显然我们不能通过改代码,去掉写日志的代码之后重新发布来做这件事。常规地,我们通过日志分级来应对这个问题。通过不同的日志分级,以及日志输出开关,实时地调整日志输出的细节程度。因此,在我们编写输出日志的代码时,就务必要注意即将输出的日志应当是什么级别。Trace、Debug、Warning、Error、Fault,这些级别,应当对应不同重要程度、不同使用场景的细节。

考虑了以上三个方面,在开发完成之后,我们还应当切换不同的身份、角度以及配置不同的日志输出级别,来“设身处地”地审视输出的日志文件,是否能够满足要求,这样才能写一份好的日志记录。

日志的组织形式应该怎样
既然叫“日志”,那我们通常的组织形式变是以时间为顺序来组织的一系列文件。除此之外,还可以将日志写入数据库、外部分析系统等等。

考虑“Separation of Concerns”,日志的组织形式,也可以根据上文考虑的不同方面来组织,比如将Error及以上的日志冗余独立记录,将面向运维的启停、加载信息独立记录,将软件运行日志和业务处理日志分开记录等等。关键是“Concern”,编写记录日志的代码时,我们应该对这段代码的功能、重要性、在整个系统的角色有深刻的认知,从而才能以不同的“关切”来考虑日志应该怎么输出,怎么组织。

综上
当然,根据软件系统的不同,其日志的侧重点也可能不同。但总体来说,日志就如同飞机的黑匣子一样重要,我们应当重视日志输出的编写工作,而绝非仅仅是完成核心业务代码的编写。

python书写日志的重要性?的更多相关文章

  1. Python之日志处理(logging模块)

    本节内容 日志相关概念 logging模块简介 使用logging提供的模块级别的函数记录日志 logging模块日志流处理流程 使用logging四大组件记录日志 配置logging的几种方式 向日 ...

  2. 【转】Python之日志处理(logging模块)

    [转]Python之日志处理(logging模块) 本节内容 日志相关概念 logging模块简介 使用logging提供的模块级别的函数记录日志 logging模块日志流处理流程 使用logging ...

  3. Python logging(日志)模块

    python日志模块 内容简介 1.日志相关概念 2.logging模块简介 3.logging模块函数使用 4.logging模块日志流处理流程 5.logging模块组件使用 6.logging配 ...

  4. Python之日志处理 logging模块

    Python之日志处理(logging模块)   本节内容 日志相关概念 logging模块简介 使用logging提供的模块级别的函数记录日志 logging模块日志流处理流程 使用logging四 ...

  5. Python之日志处理(logging模块)转载

    本人主要做一个知识的归类与记录,如是转载类文章,居首都会备注原链接,尊重原创者,谢谢! 此文转载原链接:https://www.cnblogs.com/yyds/p/6901864.html 本节内容 ...

  6. Python之日志处理(logging模块一基础)

    转载自:https://www.cnblogs.com/yyds/p/6901864.html 本节内容 日志相关概念 logging模块简介 使用logging提供的模块级别的函数记录日志 logg ...

  7. python logging 日志轮转文件不删除问题

    前言 最近在维护项目的python项目代码,项目使用了 python 的日志模块 logging, 设定了保存的日志数目, 不过没有生效,还要通过contab定时清理数据. 分析 项目使用了 logg ...

  8. a:hover和a:visited书写顺序的重要性

    2a:hover和a:visited书写顺序的重要性今天在用a:hover属性的时候发现一个奇怪的问题,同一个页面里面有些链接的a:hover效果不能正常表现出来.链接的代码是一样,没有使用其它样式固 ...

  9. python标准日志模块logging及日志系统设计

    最近写一个爬虫系统,需要用到python的日志记录模块,于是便学习了一下. python的标准库里的日志系统从Python2.3开始支持.只要import logging这个模块即可使用.如果你想开发 ...

随机推荐

  1. Wannafly交流赛1 B 硬币[数学思维/贪心]

    链接:https://www.nowcoder.com/acm/contest/69/B来源:牛客网 蜥蜴的生日快到了,就在这个月底! 今年,蜥蜴的快乐伙伴之一壁虎想要送好多个1元硬币来恶整蜥蜴. 壁 ...

  2. BeanFactory和ApplicationContext的异同

    相同: Spring提供了两种不同的IOC 容器,一个是BeanFactory,另外一个是ApplicationContext,它们都是Java interface,ApplicationContex ...

  3. Css 基础学习

    css 基本选择器 css基本选择器有三种方法 第一种: class选择器 .c1{ color: red;} <div class='c1'>hello world</div> ...

  4. 盘点支持Orchard的.NET 4.5虚拟主机(虚拟空间)

    Orchard作为.NET社区最为先进的开源项目之一,已经被越来越多的人使用, 由于它使用了最时髦的微软技术栈(.NET4.5),因此在 Win2008+和IIS7+ 的环境上运行最为完美, 而win ...

  5. 多字节与UTF-8、Unicode之间的转换

    from http://blog.csdn.net/frankiewang008/article/details/12832239 // 多字节编码转为UTF8编码 bool MBToUTF8(vec ...

  6. java中的占位符\t\n\r\f

    \t 相当于tab,缩进\n NewLine 换行 System.out.println("aaa\tbbb"); //aaa bbbSystem.out.println(&quo ...

  7. Ethernet帧格式

    一.Ethernet帧格式的发展 1980 DEC,Intel,Xerox制订了Ethernet I的标准 1982 DEC,Intel,Xerox又制订了Ehternet II的标准 1982 IE ...

  8. HTML5 Canvas 绘制旋转45度佛教万字

    效果如下: 代码如下: <!DOCTYPE html> <html lang="utf-8"> <meta http-equiv="Cont ...

  9. Async.js解决Node.js操作MySQL的回调大坑

    因为JavaScript语言异步特性.在使用Node.js运行非常多操作时都会使用到回调函数,当中就包含訪问数据库.假设代码中的业务逻辑略微复杂一点,回调一层层嵌套.那么代码非常easy进入Callb ...

  10. winform制作自定义控件

    一 .概述Windows 窗体控件是可再次使用的组件,它们封装了用户界面功能,并且可以用于客户端 Windows 应用程序.“Windows 窗体”不仅提供了许多现成控件,还提供了自行开发控件的基础结 ...