Xiao_bird博客

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

我是做Linux下服务器开发的,参与的项目都是在已经应用的代码上再开发新的功能。暂且放下什么代码清晰、注释清楚这一类老人的教诲,来看看这些项目中打印的日志。至于为什么要定个原则再打日志,估计很多人心里也有数,但是,具体要定个什么样的原则呢?暂且看看在我的项目中这些让人头疼的日志。

日志是个有用的东西,优点若干,缺点——就是没利用好它的优点。我的项目中,打日志当然不会用printf,write之类直接调用系统IO函数,不过,虽然加上了一层封装,但封装的功能公限于在每行日志前加时间、日志级别,并在日志文件大于一个限制时将文件进行备份。我觉得这种封装是每个项目都会用的,而且也是最基本的要求。

在这层封装之上,我的项目中唯一有的原则:出错用ERROR,其它都用INFO。首先说明一下,我们的日志不只像 log4j一样分info,error等,每种日志还要份出级别,比如info1,info2…,数字越大,显示的日志越多。言归正传,除了这个原则,真的很自由,想写什么,就写什么,最后生成的日志不成体系,增加了日志分析的困难。我总结了一下,列举出来,同时,做为制定原则的根据:

1、日志分级不清。除了INFO、ERROR两类日志,对具体的分级,项目中并没有进行明确定义。导致代码中为了省事,大部都是INFO1,在分析日志时,无法有效根据日志级别过滤日志。同时,服务真正上线运行时,也无法通过设定日志级别,来限制日志数量。

2、没有对ERROR种类做出定义。虽然一说大家都知道,ERROR就是出错的日志,但是,什么情况下才是真正的出错?比如,别人给我发了一个请求,如果我已经有对应资源,就用这个资源来处理,如果还没有,就新建一个。但是,在查找资源的操作中,如果资源没找到,就打了个ERROR出来,这恐怕不合适。

3、日志格式散漫。语言这个东西是极其自由的,用一两句完整的自然语言来描述当前的一个状态,虽然是最清楚的,但是,别忘了,我们的日志并不是就您这一句话!我们也不是在写文章!而且,你也不可能保证每次日志都使用同一个句型,这样的日志打出来,分析日志的人要看应对各种形式的句型变换,而且最恐怖的是还要把一整句话里的每一个词都看清楚才能确定这条日志的真正含意!不要让我们的日志读者感觉到他的工作像在在读古文!补充一句,现在的软件日志大多都用英文,写日志、读日志的人,英文水平参差不齐,这就更加恐怖了!

4、没有明显的会话标识。这是什么意思呢?做服务软件,基本都是多线程在跑,大家都往一个日志文件里写东西,你一句,我一句,最后我来分析日志的时候呢?鬼也不知道你这句日志是处理谁的时候打出来的!尤其是在做性能测试的时候,日志基本上就无用武之地了,一旦出了错误,你让老天怎么帮你?

 

好了,问题说完了,该讨论一下怎么改进了,也就是到了定原则的时候了。不过,项目特点不一样,也请您提出自己的看法。

1、日志明确分级。这应该是广义的分级,还应该包括日志分类。比如,如果日志分成4个级别,那么,各级别对应的信息可以这样划分:

    1级:服务启动、停止的信息,影响服务运行时状态的信息。即,针对整个服务的信息,而不是对单个处理而言的

    2级:关键的流程信息。目标就是让分析人可以通过这一级日志了解到业务流程中的关键点,而不是处理细节

    3级:关键的处理点信息。应该包含处理请求时的关键点,比如这个请求在服务内部是怎么来运做的

    4级:琐碎的信息。比如输出一些变量的值啥的,有点调试的意思

    在上面这几个级别的基础上,我认为对于3、4级中产生的ERROR,应该提高一级打印。即,如果在第4级的日志点出现了ERROR,应该打印为ERROR3,以此类推。而ERROR1和ERROR4,则需要根据需要来定义了。

    再来说日志的分类,这个分类,并不是简单地分成INFO,ERROR,Debug之类的,而是按服务的种类来分,比如您的项目中可以为日志定义其归属于不同的模块,这样我在查问题的时候,就可以针对某个模块来开关日志了。

2、对ERROR做出明确定义。ERROR日志和其它日志不同,因为它很不讨人喜欢。当我在我的日志中看到ERROR时,第一个感觉就是:我要加班了。所以,我认为在项目中,对ERROR做出一个明确的定义,是很必要的。不过,我并不是说要写个文档,规定哪些情况可以算ERROR,因为我们的项目太大了,这种情况估计也写不完,就是写了估计也没人看。我的意思,是对ERROR做个定义,比如“出现了非正常的运行结果,或是这种情况的出现是有悖于我的设计的”类似,不过,这个定义似乎并不好写,但是即便是我们在项目的进行中对它进行数次修改,也比没有这个约束,即兴发挥强。

3、重头戏:规范日志格式。其实,我认为真的没有必要用完整的自然语言来描述一个运行时状态。我们写日志的目标,应该是简洁明了,能够用最少的词汇清楚地表达一个意思,才是一个成功的日志输出。而且,这个问题可以结合之上第4个问题“没有明显的会话标识”,一起来解决。比如

【时间】【种类及级别(比如INFO1)】【会话标识】日志信息

而且,限于我们可怜的屏幕输出宽度,请尽量缩短每个字段的长度,比如“时间”里就不要打日期了,可以在日志文件里每天占用一行打印一个日期就足够了;同时,最好各个字段能够对齐,便于观察和分析。最自由的日志信息,请尽量用最简短的语言进行描述,不要长篇大论了,哪怕是 The Resources is not exist,也请用Resource Not Found来代替吧!不要怕这样打出来的一堆日志像油条一样细,因为,有很多时候即便用最少了字数,也要写出很长的输出,相信我!此外,长短不一的日志还能刺激阅读者的神经,我想他们更喜欢曲线而不是水桶。

4、对描述的建议。对关键的一些日志点可以打一些特别的标记,比如一个资源初始申请的时候,可以打上“___/ New Life \____”,等等,这样便于在海量的日志中寻找关键点,但是,千万注意,这些看上去很酷的标记一定谨慎使用,别把日志打成涂鸦!

 

这几点只是我当前想到的,我真的希望看到更好的建议,我的目的只是想看到一个“结构化的”日志,也许将来的哪天还会有人提出“面向对象的”日志。但是目前来看,基于以上这三点优化,我已经可以提出几个方便使用的工具来分析日志:

1、再不怕性能测试的日志无据可查,因为我们有了会话标识!因为我们的日志是“结构化”的,很容易提取出每行日志所属的会话信息,所以,写个工具吧,如果你懒得写,甚至用grep都可以,目标就是:只看我们想要看的!

2、提取出了单独会话的信息还不满足?没问题,你可以过滤掉你不想看的!根据什么?当然是日志级别!同样,grep一样可以胜任!

3、这个单从上面的原则就表现不出来了。回顾一下我的第1个优化目标:日志分类!我们可以通过某种设计,利用配置文件来屏蔽掉某些模块的日志,同时开放另一些,而对于单个模块,还可以定义不同的日志级别!

 

怎么样,有了这些,分析日志会不会像是一种享受:)

posted on 2009-07-01 14:20  Xiao_bird  阅读(783)  评论(3编辑  收藏  举报