开发者花了很多时间和精力在应用中加入日志输出,以此表明应用正常运行。当异常发生时,可以知道究竟出现了什么错误。这些日志文件通常可以说明我们的应用每天运行究竟是正常的还是异常的。
在这里,我将忽略其它技术。比如为应用增加类似HTTP或JMX监视器。这些技术提供的是应用程序即时信息,而不是本文讨论的二级监视结果。
监控日志文件通常有三种方式:
1. 从不检查;
2. 被动检查;
3. 主动检查。
从不检查意味着那些应用一直运行从不停止,而且也不需要检查。这一点我敢打赌。
被动检查是很常见的。举个例子,Smith太太打电话投诉当她想要买一双新鞋时,网站就瘫痪了。她已经支付了两次,但是从没收到过鞋子。在这个传统 的公司中,开发者和运维工程师是被完全隔离的。必须从运维工程师获得该问题发生时的日志,开发者才能开始分析。但是从运维那里返回的往往是一些完全不相关 的日志,接下来开发者不得不再次向他们索要日志,甚至如此反复多次。这个过程耗费了几周时间,Smith太太变得怒不可遏。最后,日志终于到了开发者手 中,问题解决。
可能很多公司都像上面“被动检查”的场景中描述的那样,开发者不被信任或允许操作在线服务器。这种情况司空见惯,我们中的绝大部分人都遇到过这种情况。我们应当信任开发者去操作在线系统。然而,作为一个开发者,在操作在线系统之前,必须记住两条黄金定律:
1. 不要停止任何东西;
2. 如果停止某些东西,请确保有人会在身边提醒你。
“主动检查”意味着检查日志文件要成为一个定期任务:每天、每小时或其它间隔定期执行。即使你的应用包含了大量的JMX、http或其他监视器,也不能确保一定会能发现每个问题。监视器只能发现你设定问题,除此之外的其他任何问题都不会报告。
再回到要我帮忙的问题,可能是历史的或其他原因,通过手动检查日志文件来监控系统运行,通常要对一些文件进行剪切或粘贴操作。这些重复的剪切和粘贴操作,每周大概会占用一个人半天的工作时间。
我非常不喜欢这些工作。我不善于这些需要手动且易出错的重复无聊的工作。每周要消耗半天人力,所以将这项任务自动化显然更符合成本效益。只要时间不是花在追求完美的解决方案上。那么,有什么选择呢?
如果你看了日志的规模,你一定会喜欢上Splunk,它能够监控多个消息源(譬如系统的日志守护进程)的消息。
这就意味着向Splunk发送错误只是简单地建立一个Log4j的系统日志附加器,不过那不是这篇博文的范畴…
最后,你需要写一些shell脚本来完成一些类似于“grep”命令的功能,将结果写入文件,并将这些文件通过邮件发送给你。
开发一个基于Spring的app有多难?它需要包含一些尽可能通用的、可重用的类,能够定期检查错误日志文件并将结果通过邮件发送给你。当然,结果还是通过邮件发送比较好,因为你总是会习惯性地查看你的邮箱。
开始
在其他类似的工程当中,都面临着如何迈出第一步的问题。要想让这个工程发布,需要写哪些类。有很多方法来确定你需要写哪些类,譬如简单地凭直觉,或者利用类似UML的设计工具,或者用快速原型或测试驱动开发。在每种情况下,你真正要做的就是让类名体现的功能满足一些要求。例如,在这里我需要:
1. 搜索一个给定的路径和子路径,找出某种特定类型的文件。
2. 检查找到文件的时间,判断是否有必要在这个文件中搜索错误。
3. 时间满足要求,则在其中查找异常。
4. 找到异常,则判断是否是我们关注的,还是需要忽略它。
5. 如果异常是我们关注的,则将其加到报告中。
6. 检查完所有文件后,形成待发布报告。
7. 通过邮件或其他方式发布报告。
8. 以上所有操作每天定时执行。
这些操作就形成了几个类名:FileLocator、FileValidator、RegexValidator、FileAgeValidator和Report。
上述几个类名中包含了多次的“Validator”,意味着我们可以用一个接口,叫做“Validator”。利用接口的几个实现来完成上面的验证工作。这些实现可以结合起来组成一个应用。
这只是一个初步的想法。如果你看了代码,会发现没有一个类名是Report,只有一个Results类和重构的Formatter接口、TextFormatter和HtmlFormatter类、Publisher接口和EmailPublisher类。
为了让任务定期执行,有多种选择。首先,需要将java代码和调用它的脚本放在一起,然后放在Unix机器上执行。但是这就意味着该应用不能在 Windows上运行,并且只能作为一个独立的应用。这是个大问题,所以我们可以利用Spring和Quartz调度,使得建立一个调度任务非常简单。
而且Spring提供了一个非常好的Java邮件类和Email模板,这对我们的报告邮件非常有用。
这些只是开始,关于类设计一些模糊的想法通过一种松耦合的方式连接在一起组成了我们的应用。如果在正式的工作中,你可能需要花时间把这些整理成文档,甚至需要画出类图,加在一个Doc文档中,然后多次复查直到都不在改变。但是,我不需要去管这些…
配置应用
和其他应用一样,我们需要指出系统建立必须的属性值以及它们是如何被使用的。这个应用由app.properties文件配置,路径为src/main/resources。
# The path to the log file directory to scan for errors
scan.in=/Library/Tomcat/logs
# A regex defining what to look for - or what not to include
scan.for=^.*Exception.*
exclude=^.*IllegalStateException.*
# The number of following lines to add to the report
following.lines=10
# Where to email the report
# The max age of a file in days
max.days=1000
第一个我们感兴趣的属性是scan.in,它是Web服务器的日志路径,作为类FileLocator的输入参数。