日志实践推荐

背景



软件系统生产稳定,依靠着各种高可用、高吞吐、高性能的设计。一旦出现生产问题,常常需要线上定位问题。

日志则是必备的,问题定位利器。常常出现线上问题,我们都可以通过日志精确定位。同时在开发过程中,由于极长的调用链难以快速定位问题或难以复现时,它是极好的利器。

日志级别



一个项目各个log级别的定义应该是清楚明确的,是每个开发人员所遵循的;

即使是TRACE或者DEBUG级别的日志,也应该有一定的规范,要保证除了开发人员自己以外,包括测试人员和运维人员都可以方便地通过日志定位问题;

FATAL

表示需要立即被处理的系统级错误。

当该错误发生时,表示服务已经出现了某种程度的不可用,系统管理员需要立即介入。

这属于最严重的日志级别,因此该日志级 别必须慎用,如果这种级别的日志经常出现,则该日志也失去了意义。

通常情况下,一个进程的生命周期中应该只记录一次FATAL级别的日志,即该进程遇到无 法恢复的错误而退出时。

当然,如果某个系统的子系统遇到了不可恢复的错误,那该子系统的调用方也可以记入FATAL级别日志,以便通过日志报警提醒系统管 理员修复;

ERROR

该级别的错误也需要马上被处理,但是紧急程度要低于FATAL级别。

当ERROR错误发生时,已经影响了用户的正常访问。从该意义上来说,实际上 ERROR错误和FATAL错误对用户的影响是相当的。

FATAL相当于服务已经挂了,而ERROR相当于好死不如赖活着,然而活着却无法提供正常的服务,只能不断地打印ERROR日志。

特别需要注意的是,ERROR和FATAL都属于服务器自己的异常,是需要马上得到人工介入并处理的。

而对于用户自己 操作不当,如请求参数错误等等,是绝对不应该记为ERROR日志的;

WARN

该日志表示系统可能出现问题,也可能没有,这种情况如网络的波动等。

对于那些目前还不是错误,然而不及时处理也会变为错误的情况,也可以记为WARN日 志,例如一个存储系统的磁盘使用量超过阀值,或者系统中某个用户的存储配额快用完等等。

对于WARN级别的日志,虽然不需要系统管理员马上处理,也是需要 即使查看并处理的。

因此此种级别的日志也不应太多,能不打WARN级别的日志,就尽量不要打;

INFO

该种日志记录系统的正常运行状态,例如某个子系统的初始化,某个请求的成功执行等等。

通过查看INFO级别的日志,可以很快地对系统中出现的 WARN,ERROR,FATAL错误进行定位。

INFO日志不宜过多,通常情况下,INFO级别的日志应该不大于TRACE日志的10%;

DEBUG or TRACE

这两种日志具体的规范应该由项目组自己定义,该级别日志的主要作用是对系统每一步的运行状态进行精确的记录。

通过该种日志,可以查看某一个操作每一步的执 行过程,可以准确定位是何种操作,何种参数,何种顺序导致了某种错误的发生。

可以保证在不重现错误的情况下,也可以通过DEBUG(或TRACE)级别的 日志对问题进行诊断。

需要注意的是,DEBUG日志也需要规范日志格式,应该保证除了记录日志的开发人员自己外,其他的如运维,测试人员等也可以通过 DEBUG(或TRACE)日志来定位问题;

在出错时,日志中包含尽量多的有用上下文信息


为什么可以这么做?

日志过多大家伙会说影响性能,但是值得指出的是出错是小概率分支。如果是出错是大概率分支那,打日志以外操作更会成为瓶颈!

多打日志减少支持时间,比起开发所用的实现时间,线上和线下的排查/支持要花费很多时间;

别吞噬异常!

抓住异常没有书写人和响应日志,将导致难以定位。

    @Override

    public UserAmountStat getUserYestodayStat(Long userId, String day) throws GlobalServiceException {

        // TODO Auto-generated method stub

        try {

            UserAmountStat stat = userAmountStatMapper.getUserYestodayStat(userId, day);

            if (stat == null) {

                stat = new UserAmountStat();

                stat.setBet(0l);

                stat.setPrize(0l);

                stat.setBonus(0l);

            }

            return stat;

        catch (Exception e) {

            // TODO: handle exception

            throw new GlobalServiceException(e);

        }

    }

此处推荐的需要在日志中记录的内容

  • 在系统启动或初始化时记录重要的系统初始化参数
  • 记录系统运行过程中的所有的错误
  • 记录系统运行过程中的所有的警告
  • 在持久化数据修改时记录修改前和修改后的值
  • 记录系统各主要模块之间的请求和响应
  • 重要的状态变化(如对系统白名单的修改等)
  • 系统中一些长期执行的任务的执行进度
  • 服务信息:接口、方法、版本等等
  • 如果是超时,配置的超时时间,本次处理所用的时间,是Server端超时还Client超时?
  • 重试的次数,本次重试的是第几次(fail over)

RequestID

将一个请求的整个处理流程和唯一的requestID关联起来,requestID规则另行定义。

日志输出级别

在设置日志输出级别时,推荐如下:

  • 开发、测试环境打开DEBUG;
  • 线上生产环境保证设置为WARN级别;

关于日志分类



日志从功能来说,可分为诊断日志、统计日志、审计日志。

诊断日志:

  • 请求入口和出口
  • 外部服务调用和返回
  • 资源消耗操作: 打开文件等
  • 容错行为: 譬如云硬盘的副本修复操作
  • 程序异常: 譬如数据库无法连接
  • 后台操作:清理程序
  • 启动、关闭、配置加载
  • 抛出异常时,不记录日志

统计日志:

  • 用户访问统计
  • 计费日志(如记录用户交易流水日志,格式较为严格,便于统计)

审计日志:

  • 管理操作(类似于登录信息记录)

关于日志格式



日志格式一定要统一,不能任由开发人员的喜好来。举例来说,对于NOS视频截图超时的ERROR日志,有以下几种方式打印:

第一种:

logger.error(“Gearman timeout exception for request ” + getRequestID() + ” value: ” + value, e);

第二种:

logger.error(“RequestID: ” + getRequestID() + “, Error Message: Gearman timeout exception: ” + e);

第三种:

logger.error(getErrorMessage(getRequestID(), getErrorMessage(), e));

第一种方式打印日志即是开发人员按照自己的喜好来的,这种方法带来的问题是:

  • 系统中日志格式不统一,不利于自动化处理
  • 有些日志可能只有开发人员自己才能看懂
  • 代码规范性不好

而第三种方式,通过一个函数来规范日志格式,所有开发人员便可以通过该接口实现统一的日志。

关于日志语义



日志书写语义一定要明确,定义明确语义的异常类信息,在此列举linux环境下两个报错信息作为示例;

[root@ip-172-31-1-43 ~]# cd /file

-bash: cd: /file: 没有那个文件或目录

[root@ip-172-31-1-43 ~]# cd build-public-ult_6.0-2015-09-02-17_6d3c3ee51a.tar.gz

-bash: cd: build-public-ult_6.0-2015-09-02-17_6d3c3ee51a.tar.gz: 不是目录

我们可以看到同样是cd命令,在遇到不同的错误行为时,分别针对性的给出了报错信息。

时间: 2024-08-25 09:48:21

日志实践推荐的相关文章

网易视频云分享:最佳日志实践

网易视频云是网易倾力打造的一款基于云计算的分布式多媒体处理集群和专业音视频技术,提供稳定流畅.低时延.高并发的视频直播.录制.存储.转码及点播等音视频的PAAS服务,在线教育.远程医疗.娱乐秀场.在线金融等各行业及企业用户只需经过简单的开发即可打造在线音视频平台.现在,网易视频云的技术专家给大家分享一则技术文:最佳日志实践. 前言 日志用来记录用户操作.系统运行状态等,是一个系统的重要组成部分.然而由于日志并非系统核心功能,通常情况下并不受团队的重视.在出现问题需要通过日志来定位时,才发现日志还

每个 Python 程序员都要知道的日志实践

在现实生活中,记录日志非常重要.银行转账时会有转账记录:飞机飞行过程中,会有黑盒子(飞行数据记录器)记录飞行过程中的一切.如果有出现什么问题,人们可以通过日志数据来搞清楚到底发生了什么. 对于系统开发.调试以及运行,记录日志都是同样的重要.如果没有日志记录,程序崩溃时你几乎就没办法弄明白到底发生了什么事情.举个例子,当你在写一个服务器程序时,记录日志是非常有必要的.下面展示的就是 EZComet.com 服务器的日志文件截图. 服务崩溃后,如果没有日志,我几乎没办法知道到底发生了错误.日志不仅对

[转载] 每个 Python 程序员都要知道的日志实践

原文: http://python.jobbole.com/81666/ 在现实生活中,记录日志非常重要.银行转账时会有转账记录:飞机飞行过程中,会有黑盒子(飞行数据记录器)记录飞行过程中的一切.如果有出现什么问题,人们可以通过日志数据来搞清楚到底发生了什么. 对于系统开发.调试以及运行,记录日志都是同样的重要.如果没有日志记录,程序崩溃时你几乎就没办法弄明白到底发生了什么事情.举个例子,当你在写一个服务器程序时,记录日志是非常有必要的.下面展示的就是 EZComet.com 服务器的日志文件截

oracle 11g 之LogMiner分析重做日志实践

1.安装LogMiner 以DBA用户身份运行下面2个脚本: dbmslm.sql用来创建DBMS_LOGMNR包,该包用来分析日志文件. SQL> @$ORACLE_HOME/rdbms/admin/dbmslm.sql; Package created. Grant succeeded. Synonym created. dbmslmd.sql用来创建DBMS_LOGMNR_D包,该包用来创建数据字典文件. SQL> @$ORACLE_HOME/rdbms/admin/dbmslmd.sq

大数据学习路线及各阶段学习书籍推荐

大数据学习路线及各阶段学习书籍推荐!废话不多说,直接切入主题,有需要的小伙伴可以参考学习! 阶段一.大数据基础--java语言基础方面 (1)Java语言基础 Java开发介绍.熟悉Eclipse开发工具.Java语言基础.Java流程控制.Java字符串.Java数组与类和对象.数字处理类与核心技术.I/O与反射.多线程.Swing程序与集合类 (2) HTML.CSS与JavaScript PC端网站布局.HTML5+CSS3基础.WebApp页面布局.原生JavaScript交互功能开发.

自学大数据者请进:大数据学习线路及各阶段学习书籍、视频推荐

大数据学习路线及各阶段学习书籍推荐!废话不多说,直接切入主题,有需要的小伙伴可以参考学习! 阶段一.大数据基础--java语言基础方面 自学大数据者请进:大数据学习线路及各阶段学习书籍.视频推荐(1)Java语言基础 Java开发介绍.熟悉Eclipse开发工具.Java语言基础.Java流程控制.Java字符串.Java数组与类和对象.数字处理类与核心技术.I/O与反射.多线程.Swing程序与集合类 在这里相信有许多想要学习大数据的同学,大家可以+下大数据学习裙:740041381,即可免费

2015第30周四Java日志组件

Java 日志 API 从功能上来说,日志 API 本身所需求的功能非常简单,只需要能够记录一段文本即可.API 的使用者在需要进行记录时,根据当前的上下文信息构造出相应的文本信息,调用 API 完成记录.一般来说,日志 API 由下面几个部分组成: 记录器(Logger):日志 API 的使用者通过记录器来发出日志记录请求,并提供日志的内容.在记录日志时,需要指定日志的严重性级别.当 程序中需要记录日志时,首先需要获取一个日志记录器对象.一般的日志记录 API 都提供相应的工厂方法来创建记录器

简单的php自定义错误日志

平时经常看php的错误日志,很少有机会去自己动手写日志,看了王健的<最佳日志实践>觉得写一个清晰明了,结构分明的日志还是非常有必要的. 在写日志前,我们问问自己:为什么我们有时要记录自定义的日志呢?而不用系统默认的日志记录方式呢? 我认为有两个原因: 1.团队需要一个统一格式的日志方便管理 2.大量无用错误日志占据硬盘空间,仅需记录有意义的日志. 那么,实践一下. 1.打开你的php.ini 2.打开日志记录,将 log_errors = Off 改成 log_errors = On 3.将p

【转】java日志组件介绍(common-logging,log4j,slf4j,logback )

common-logging common-logging是apache提供的一个通用的日志接口.用户可以自由选择第三方的日志组件作为具体实现,像log4j,或者jdk自带的logging, common-logging会通过动态查找的机制,在程序运行时自动找出真正使用的日志库.当然,common-logging内部有一个Simple logger的简单实现,但是功能很弱.所以使用common-logging,通常都是配合着log4j来使用.使用它的好处就是,代码依赖是common-loggin