日志标准化规范新范本模板.docx
《日志标准化规范新范本模板.docx》由会员分享,可在线阅读,更多相关《日志标准化规范新范本模板.docx(11页珍藏版)》请在冰点文库上搜索。
日志标准化规范新范本模板
日志标准化规范
一.背景
随着互联网络的飞速发展,各行各业已经不限于知道信息,更是挖掘、把握住隐藏在信息后面的信息。
海量的数据是一种宝贵的财富,如何按照不同维度、各种口径和规则从海量的、隐含的、杂乱的、重复的web日志或用户访问信息中发现、提炼、分析、统计出有用的知识和应用价值,进而提高服务质量,改进网站的结构和内容,挖掘出有意义的用户访问模式、规则以及相关的潜在用户群等是一件非常有意义的工作。
为实时监控网络的异常状态,跟踪网络应用资源的使用情况,实现对众多设备主机日志信息的集中分析和管控,实现各种日志格式的兼容,准确定位出问题的物理服务器和时间段等,目前南航通过统一集中部署SpringAOP(kafa/redis)+Elasticsearch+Logstash+Kibana日志分析平台实现了对日志收集、存储、搜索、分析、监控及展现,并开放访问接口给开发人员,开发人员以ELK日志分析平台的源数据为基础,对数据进行预处理、维度汇总,进而形成行业上的各种指标。
ELK具有强大的搜索和展现功能,它只需安装部署而不需要编写代码,即可进行业务数据分析、错误日志分析及数据预警等。
而SpringAop是OOP的延续,它就像刀切豆腐一样横切整个系统,将“关注"封装在切面中,实现了调用者与被调用者之间的解耦合,是需要人工编写相关的代码实现日志的输出的,而在现实中日志记录无统一规范,导致无法准确快速的定位问题或者获取到想要的数据.所以本文将日志的规范重点放在SpringAop上.
二.原则
1.集中的日志服务器:
在WEB集群节点越来越多的情况下,让开发及系统维护人员能很方便的查看日志信息。
2。
日志信息输出策略:
日志信息输出全而不乱,便于跟踪和分析问题。
3.关键业务的日志输出:
基于数据采集、数据核查、系统安全等方面的考虑,关键业务系统对输出的日志信息有特殊的要求,需要做针对性的设计。
4.支持备份与保密机制:
防止日志丢失,敏感信息应加密,分布式文件系统保证可靠性。
三.日志分类
日志文件按应用需求功能分为访问日志、应用日志和系统日志。
按等级从低到高分为TRACE级、DEBUG级、INFO级、WARN级、ERROR级、FATAL级六级。
1.TRACE级、DEBUG级:
理论上“不属于错误",只是打印一些状态、提示信息,以便开发过程中观察,开发完成、正式上线后需要屏蔽。
2.INFO级:
理论上“不属于错误",只是一些提示性的信息,但是即使在开发完成、正式上线的系统中,也有保留的价值.在实际环境中,系统管理员或者高级用户要能理解INFO输出的信息并能很快的了解应用正在做什么.比如,一个和处理机票预订的系统,对每一张票要有且只有一条INFO信息描述"[Who]bookedticketfrom[Where]to[Where]"。
3.WARN级:
属于轻微的“警告",程序中出现了一些异常情况,但是影响不大,还可以正常使用.
4。
ERROR级:
属于“普通的错误”,在程序可以控制的范围内,不会造成连锁影响或巨大影响,日志发生之后其实不会导致系统运行出现异常的,可能是对某些数据的初始化深入验证出现的问题.
5.FATAL级:
属于“致命错误”,开发过程中的try..。
catch模块中抛出的一些未能预料到的系统错误,可导致整个系统或者一系列功能无法使用,甚至导致系统瘫痪、关闭,必须马上有人进行处理。
比如:
空指针异常,数据库不可用,如硬盘空间满等,关键业务流程中断等等.
四.代码日志规范
1。
【强制】系统应用中不可直接使用日志系统(Log4j、Logback)中的API,而应依赖使用日志框架SLF4J中的API,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。
importorg.slf4j。
Logger;
importorg。
slf4j.LoggerFactory;
privatestaticfinalLoggerlogger=LoggerFactory.getLogger(Abc。
class)。
2.【强制】日志文件推荐至少保存15天,因为有些异常具备以“周”为频次发生的特点。
3.【强制】应用中的扩展日志(如打点、临时监控、访问日志等)命名方式:
appName_logType_logName.log.logType:
日志类型,推荐分类有stats/desc/monitor/visit等;logName:
日志描述。
这种命名的好处:
通过文件名就可知道日志文件属于什么应用,什么类型,什么目的,也有利于归类查找.
正例:
mppserver应用中单独监控时区转换异常,如:
mppserver_monitor_timeZoneConvert。
log说明:
推荐对日志进行分类,如将错误日志和业务日志分开存放,便于开发人员查看,也便于通过日志对系统进行及时监控.
4。
【强制】对trace/debug/info级别的日志输出,必须使用条件输出形式或者使用占位符的方式.
说明:
logger。
debug(”Processingtradewithid:
”+id+"symbol:
"+symbol);如果日志级别是warn,上述日志不会打印,但是会执行字符串拼接操作,如果symbol是对象,会执行toString()方法,浪费了系统资源,执行了上述操作,最终日志却没有打印。
正例:
(条件)
if(logger。
isDebugEnabled()){
logger.debug(”Processingtradewithid:
"+id+”symbol:
"+symbol);
}
正例:
(占位符)
logger.debug("Processingtradewithid:
{}symbol:
{}",id,symbol);
解释:
debug/info级别的信息,信息本身需要计算或合并的,必须加isXxxEnabled()判断在前,这样可以大大提高高并发下的效率。
如果不加isXxxEnabled()判断,"Processingtradewithid:
"+id+”symbol:
”+symbol在info级别下也会执行。
5。
【强制】避免重复打印日志,浪费磁盘空间,务必在log4j。
xml中设置additivity=false。
正例:
〈loggername=”com.taobao。
dubbo.config”additivity=”false”〉
6。
【强制】异常信息应该包括两类信息:
案发现场信息和异常堆栈信息。
如果不处理,那么通过关键字throws往上抛出。
正例:
logger.error(各类参数或者对象toString+"_"+e.getMessage(),e);
7.【推荐】谨慎地记录日志。
生产环境禁止输出debug日志;有选择地输出info日志;如果使用warn来记录刚上线时的业务行为信息,一定要注意日志输出量的问题,避免把服务器磁盘撑爆,并记得及时删除这些观察日志。
说明:
大量地输出无效日志,不利于系统性能提升,也不利于快速定位错误点.记录日志时请思考:
这些日志真的有人看吗?
看到这条日志你能做什么?
能不能给问题排查带来好处?
8.【参考】可以使用warn日志级别来记录用户输入参数错误的情况,避免用户投诉时,无所适从.注意日志输出的级别,error级别只记录系统逻辑出错、异常等重要的错误信息。
如非必要,请不要在此场景打出error级别.
以上8条来自于《阿里巴巴开发手册》-—-日志规约.
9.Web日志记录了用户对网站的每一次点击访问,即每一次接口的调用。
但由于各种原因,web日志中有些记录是缺失或不完整的数据,推荐在每个接口调用后,在其入口输出调用类名及输入参数的日志,以及接口结束前输出返回数据的日志,并使用info级别。
另外,重要方法入口,业务流程前后及处理的结果等,推荐记录log,并使用debug级别,因为对于非开发人员掌控的环境(无法做DEBUG),记录方法调用、入参、返回值的方式对于排查问题会有很大帮助。
10。
日志输出规范。
应用程序禁止直接使用Log4JAPI,并且禁止使用JDKConsole输出(System。
out,System。
err,ex.printStackTrace(),etc.),应使用logger。
debug、logger。
error。
所有的日志实例的属性都应从根日志(rootlogger)继承。
日志信息必须支持输出到控制台(console)和文本文件(TextFiles).输出到文本文件(TextFiles)的日志,应提供日志文件分析脚本,以方便查询阅读、统计分析。
11.关注日志记录对于系统性能、安全性的影响,不要多次重复记录日志.日志记录太过于频繁,日志记录到文件IO或者数据库都是很费CPU和内存资源的事,会对系统的性能产生影响。
关注日志是否会被恶意攻击频繁打印日志,使得日志文件超过100G、500G直到磁盘容量爆满,服务器挂掉。
12.记录要精简、不滥用日志,关注日志记录的正确性和必要性。
分清楚什么时候应该记录日志,什么时候不需要记录日志.什么是TRACE、DEBUG信息,什么是INFO、ERROR信息。
对于异常处理,不要多次重复的记录同一个异常的堆栈信息。
比如在DAO层记录了异常堆栈信息,然后抛出异常,在web层catch了异常之后,又记录了一次异常堆栈信息。
13.在日志信息上添加便于检阅、查找的额外标识。
每条日志都应有关键标识,能够尽快定位某条信息的位置。
包括日期和时间,程序Java类的名称、方法甚至行号,错误类型或者错误代码。
否则前端web页面报错,告诉开发人员去查找问题,开发人员很难去查找当时的操作日志或者异常信息。
14。
Log对象的声明和初始化
仅以下代码是符合规范:
//(推荐)
privatestaticfinalLoggerlogger=LoggerFactory。
getLogger(Xxx。
class);
privatefinalLoggerlogger=LoggerFactory。
getLogger(getClass());
privatestaticLoggerlogger=LoggerFactory。
getLogger(Xxx.class);
protectedfinalLoggerlogger=LoggerFactory.getLogger(getClass());
privateLoggerlogger=LoggerFactory。
getLogger(getClass());
protectedLoggerlogger=LoggerFactory。
getLogger(getClass());
privatestaticfinalLoggerlogger=LoggerFactory.getLogger("loggerName");
15.注意error和warn级别的区别,导致业务不正常服务的,用error级别;错误是预期会发生的,并且已经有了其他的处理流程,使用warn级别.
16.Log的内容须确保不会因为Log语句的问题而抛出异常造成中断,如下有可能会抛出NullPointerException:
log.debug(”Processingrequestwithid:
{}”,request。
getId());
17.日志配置
一般有:
日志级别、输出位置,如果有日志分析工具,还需仔细设计日志格式的配置,以能够在工具中完美展示.
所有的日志配置文件放在src目录下,编译时随同.class文件一同拷贝到(%webapp_HOME%)\WEB—INF\classes\目录下,这些配置文件推荐采用properties文件的编写方法,commons-logging。
properties文件用来指定commons-logging的实现为log4j,log4j.properties文件用来配置log4j的所有参数,日志配置信息不得配置在这两个文件以外的文件中。
18.用户操作日志。
用户操作日志面临记录频繁、数据结构异常多、数据流量非常大、数据价值如何提高等问题。
在记录用户的操作日志尽量不要浪费系统的额外性能开销,但是我们记录的信息要方便下一步的数据挖掘用户行为分析。
(1)频繁记录日志会导致系统IO的消耗,我们可以采用Redis或memcached这一类内出数据库先行记录日志当量达到一定规模自动记录到日志文件中避免平凡调用IO进行文件数据写入或数据库写入.
(2)定义统一的数据结构,这样做的目的是为了能够方便使用相应的工具进行用户操作日志挖掘。
(3)提高用户数据价值,目的是为了提高分析用户数据,分析用户数据是为了分析出一种或几种用户行为模式.要做到易于分析用户模式需要建立相应的操作日志记录结构,规定好结构进行分析就降低了复杂度.
用户日志分析有以下几点好处:
1。
高价值用户挖掘。
2。
高价值航班挖掘。
3.客户偏好收集,为了下一步进行客户建模,然后提供贴心的服务。
4.产品捆绑式销售,来自对客户的建模之后。
5.发觉社会影响力大的任务或关键人物。
有了这些结果,就可以体现用户日志价值,并尽快制定符合自己公司的记录结构。
19。
关键业务系统日志的要求
(1)权限管理日志
定义:
记录业务应用系统的用户权限分配管辖的每一个更改活动。
日志类型:
包括用户/用户组的权限指派与移除.
日志信息:
包括操作时间,系统设备的主机名和IP地址;操作用户(谁在操作);授权用户/用户组,权限资源名称、操作方式(如分配、删除、修改),操作结果(如成功、失败)
(2)帐号管理日志
定义:
记录业务应用系统上每个帐户的管理活动
日志类型:
包括用户的创建、删除、修改、禁用,帐户密码的管理,包括创建、修改等。
日志信息:
包括操作时间,系统设备的主机名和IP地址;操作用户;被管理的用户/用户组,操作方式(如创建、删除、修改、禁用),操作结果(如成功、失败)
(3)系统自身日志
定义:
记录应用系统在启动或关闭服务时或者在发生影响业务应用系统故障的活动。
日志类型:
包括服务启动、服务停止,系统故障.
日志信息:
包括操作时间,系统设备的主机名和IP地址;操作用户;操作方式(如服务启动),操作结果(如成功、失败)
(4)用户登录日志
定义:
记录业务应用系统的用户登录认证、退出活动
日志类型:
包括成功的用户登录认证,失败的用户登录认证,用户注销,用户超时退出
日志信息:
包括操作时间,系统设备的主机名和IP地址,操作用户,操作源IP,渠道信息,操作方式(如查询、插入、删除等),操作结果(成功、失败),请求花费时间、tokenid、sessionid。
(5)服务接口调用日志
定义:
使用WEB服务器或所有外部接口的调用需要记录接口访问信息,如用户浏览。
日志信息:
包括请求时间、用户IP、接口URL、HTTP状态码、接口方法、调用结果、执行时间
(6)业务访问日志
定义:
记录用户访问的业务应用系统的业务资源,这一类日志用于跟踪用户的行为分析是非常的重要的,可作为用户数据挖掘发现用户的喜好等一些信息,与5有重复。
日志信息:
包括操作时间,系统设备的主机名和IP地址,操作用户,操作源IP,访问的资源名称,操作方式(如查询、插入、删除等),操作结果(成功、失败).
20.记录异常信息是“记录所有信息”中的一个重要组成,在异常处理模块中应提供适量的错误原因信息,但很多开发人员只是把logging当做处理异常的一种方式。
他们通常返回缺省值,然后当做什么都没发生。
而有些开发人员先log异常信息,然后再抛出包装过的异常。
如:
log。
error("IOexception”,e);
thrownewMyCustomException(e);
这种方法总是会打印两次相同的stacktrace信息,因为有些地方会捕捉MyCustomException异常,然后输出导致问题的日志信息。
21。
当程序产生异常时,必须捕捉并处理异常、将异常记录到日志中(除非打算抛出异常),捕获异常后不处理也不输出log是一种非常不负责任的行为,这会造成问题很难被定位,极大地提高调试的成本。
须注意以下几点:
(1)将try/catch区段置于循环之外。
(2)尽量减小try块的体积,不要从try区段中返回。
(3)不要将异常用于程序流程控制。
(4)不要处理能够避免的异常。
(5)尽量抛出异常,顶层的main()函数截获所有的异常,并且打印(或者记录在日志中)在屏幕上。
(6)异常捕获尽量不要直接catch(Exceptionex),应该把异常细分处理。
(7)一个方法不应抛出太多类型的异常。
说明:
如果程序中需要分类处理,则将异常根据分类组织成继承关系。
如果确实有很多异常类型首先考虑用异常描述来区别,throws/exception子句标明的异常最好不要超过三个。
(8)记录异常不要保存exception。
getMessage(),而要记录exception.toString().
e.getMessage()、e.toString()、e。
printStackTrace()三者的区别:
e。
toString()获取的信息包括异常类型和异常详细消息;
e.getMessage()只是获取了异常的详细消息字符串;
e。
printStackTrace();会打出详细异常,异常名称,出错位置,便于调试用,一般一个异常至少几十行。
try{
m=1/0;
}catch(Exceptione){
System。
out。
println(e.toString());
System。
out。
println(e.getMessage());
}
输出结果:
java.lang。
ArithmeticException:
/byzero
/byzero
22.日志信息中尽量包含数据和描述:
easytoread,easytoparse,开发人员不能为了自己查找信息方便,输出类似“!
@#$%”的Log。
23。
日志保密机制。
对于“敏感”的单位信息,如名称、余额等信息,禁止使用debug以上级别的日志方法记录,在开发过程中,也应减少日志对该类信息的记录。
一些敏感信息可以打马赛克后输出,比如字符串部分内容换成*。
如:
身份证号422927194910011234,可以考虑这样输出:
42292719491*****34。
对于特别敏感的交易信息(如密码),不能输出到日志文件.输出到磁盘或数据库上的log日志应注意保密。
24。
日志备份机制。
必须先对当天日志进行压缩,再做磁带备份,生产机上保留至少15个工作日的日志备份.
25.日志记录必须支持多线程。
当应用程序同时处理多个客户的请求时,不同客户之间的日志信息写同一个日志文件时不应产生冲突,不同请求的日志信息能被显示并区分出来。
26。
日志文件命名。
即日志文件名必须满足<系统名称〉.log.yyyyMMddHH的命名规则.yyyyMMddHH表示每日整点时重新命名日志文件,以方便按时间定位日志信息;单个日志文件建议50M~~100M之间,即当日志文件超过该范围时,旧日志文件重命名为〈系统名称〉.log。
yyyyMMddHH.n(n从1开始编号以步长1递增),新日志写入<系统名称〉.log.yyyyMMddHH。
这里的〈系统名称>表示各个实际项目的英文缩写,英文缩写必须遵循单位对系统英文缩写的统一规定。