从场景出发,日志聚类还可以这么玩
背景
现如今,互联网服务已经深入到用户生活的方方面面,在基础设施基本一致的情况下,服务质量变得越来越重要,这也成为各公司的所面临的一个巨大挑战。各公司在实际运营过程中,所维护的各项业务可能面临各种各样的问题,这也就需要我们将各应用系统运行日志保存起来进行管理,以便问题排查和根因定位。因此将问题对应的异常日志及时反馈给运维和开发人员,是解决问题的关键。
但随着业务量的增长,数据量激增。一方面,为适应当前形势,各应用系统也由原本的单节点改成分布式和微服务架构,日志数量已经从开始的 MB 级别增长至 GB,TB 甚至 PB 级别。另一方面,由于开发人员水平也参差不齐,对于日志质量也无法保证,比如日志级别打印不准,无效日志过多等。一旦出现问题,传统的肉眼排查日志,就像大海捞针,极其困难。
目标
为了解决这些痛点,帮助系统人员快速发现异常和定位异常日志,我们计划从日志数据治理和日志知识库积累两方面入手。日志数据治理目的是解决日志质量问题,主要通过日志降噪后,定义日志合规率,日志冗余率等指标,来衡量各系统的日志质量,为系统日志健康度打分,以此来协助各项目组进行日志质量改造。日志知识库积累则通过日志降噪、聚合收敛后,形成日志知识库,系统负责人可以对日志内容进行标记是否需要关注和提供解决方案及改造计划;知识库的形成可以为后续的日志报警做辅助判断,便于快速定位异常日志和提供推荐解决方式。
设计
如下图所示,针对上述两个目标,我们主要分为三个部分进行模块设计,即:日志聚合模块,指标计算模块和知识库模块。日志聚合模块主要做日志降噪和聚合;指标计算模块用于辅助日志数据治理;知识库模块为了进行日志知识库积累和辅助告警决策。
实现
1)日志聚合模块
日志聚合模块主要为了进行日志降噪收敛,这里我们主要通过模板提取和文本相似度聚合的方式来实现。
工程级别聚合
由于日志聚合时,通过计算文本相似度进行聚合的时间复杂度为 n 平方,因此日志聚合首先对应用系统下各个工程的日志分别进行聚合,减少单次聚合时需要计算的日志总量,以此减少日志聚合所需要耗费的总时间。
模板提取
通常情况下,一个工程下数量最多、出现最频繁的日志往往具有相似的内容和结构,唯一的差别仅在于日志中的一些路径、IP、用户 id 等变量不同。因此通过设计日志模板,将符合不同日志模板的分别聚合,可以大幅提高日志聚合的效率。日志模板提取主要通过编写替换规则,对源日志进行数据清洗和替换,将类似路径、IP、用户 id 等变量剔除后,剩余的日志内容作为日志模板。在不影响日志整体的可读性的情况下,给定的替换规则越多,则日志提取的效果越好,整体干扰项就越低。这里我们分为通用变量替换,标准模板匹配和特殊字符过滤三部分呢。详情如下图所示:
首先通过通用变量替换常见的一些信息,如 IP,URL,证件号等信息;其次通过标准模板,对各系统的个性化日志进行提取;最后经过特殊字符过滤,将一些没有含义的特殊字符剔除,形成真正有价值的,可用的日志信息。以下给出部分替换规则,基于正则表达式进行匹配替换。如下所示:
基于正则表达式的模板提取,针对提取后的模板,进行一次日志聚合。由于很多系统都存在大量重复日志,此次聚合后,一方面,日志数量级由百万、千万级缩减至万级甚至千级,大大减少了日志的数量,从而有效降低下一步文本相似度算法的时间成本;另一方面,可以剔除变量,无效字符等干扰项,增加日志的可用性。
文本相似度算法
经过模板提取后,日志聚合的效果已经初显,但是还有部分模板无法识别的日志。这时候,我们采用一种文本相似度算法来检测每条信息的相似性,这样可以把日志中结构相似但信息不同的语素归于一类。比如某系统出现下图所示两类日志:
这类日志在结构和信息上都十分相似,但是在模板上很难进行发现和识别,为了解决这类问题,我们通过文本相似度检测来进行相似度计算,实现日志聚合的目的。文本相似度我们采用的方案是编辑距离。编辑距离是 Levenshtein 提出的用于计算字符串相似度的算法。编辑距离是指把一个字符串通过插入、删除或替换的编辑操作,变成另外一个字符串所需要的最少编辑次数。
编辑距离原理图
通过编辑距离计算“查询 xx 接口异常 com.xxxxx.xxxx.xxxx.exception.ArgumentException: 未找到对应的信息”和“xx 接口异常 com.xxxxx.xxxx.xxxx.exception.ArgumentException: 未找到对应的信息”的相似度为 0.98。针对这种相似度极高的日志,会被聚合成一条日志记录。
基于上述的相似度计算后,日志由一次聚合后的万级聚合至数百条,日志收敛效果进一步提升。
下图为某系统某段时间的日志摘要,经过聚类后形成的聚合结果:
2) 指标计算模块
基于上述聚合,已经形成了各系统工程级别聚合日志。对此,我们制定了一系列的日志指标,主要分为个体日志规范指标,工程级别规范指标和系统级别日志规范指标。个体规范指标主要包括合规性个体指标和冗余率个体指标;工程级别和系统级别指标则主要包括日志总量合规率,日志类别合规率和日志整体冗余率三大指标;我们最终会通过计算系统级别的三大指标,来得到最终的系统级别的日志健康分。通过日志健康分来为各应用系统进行日志健康度打分,得分越高则代表系统日志质量越好。下面就介绍各阶段指标的详细定义:
1. 合规性个体指标
一、 规则一:基于关键词判断“异常日志”是否合规。
如果包含“exception,error,fail,null,异常,错误,失败,出错,超时,为空,报错,不一致”关键字之一,则表示合规。
二、 规则二:单条异常信息特殊字符过多导致可读性差,引起的不合规。
例如某 ERROR 日志:------------------开始执行---。该日志特殊字符占比为 21/25=0.84。特殊字符占比过高,属于不合规日志。
三、 规则三:单条异常信息长度过长导致没有重点,引起的不合规。
在不包含上述规则一的关键字的情况下,如果长度大于预设阈值 180,则表示不合规。
四、 规则四:某段时间内频繁出现的日志,引起的不合规。
同一日志,出现频次大于预设阈值 100 次/每天,则表示不合规。
五、 规则五:补充规则,判断是否合规。
若上述四个规则皆不通过,则为合规。
2. 冗余率个体指标
一、规则一:基于日志聚合后出现次数,判断是否冗余。
若日志只出现一次,数量太少,不予判断。
二、规则二:基于日志聚合关键字占比,判断是否冗余。
例如某日志源日志为:the line length: 0。聚合关键字为:thelinelength。则关键字占比为 13/17=0.76。
三、规则三:基于汉字+特殊字符占比,判断是否冗余。
例如某 ERROR 日志:------------------开始执行---。该日志特殊字符占比 25/25=1。
四、规则四:补充规则,判断是否冗余。
若上述三个规则皆不符合,则冗余率为 0
3. 日志总量合规率
一、规则一:基于不规范日志数量,计算日志总量合规率。
4. 日志类别合规率
一、规则一:基于不规范日志类别,计算日志类别合规率。
例如某系统总日志聚合类别共 65 个,其中不合规类别为 40 个,则日志类别不合规率为:40/65=0.62。
5. 日志整体冗余率
一、规则一:基于冗余日志,计算日志整体冗余率。
6. 日志健康度评分指标
一、规则一:基于日志总量合规率、日志类别合规率和日志整体冗余率,计算日志健康分。
例如某系统日志总量合规率为 30,日志分类合规率为 60,日志冗余率为 80。预设的 A,B,C 权重为 4,2,1。则该系统日志健康分为:29 分。
通过上述一系列的日志指标,较好的区分出各系统的日志健康状况,对于日志健康分较低的系统,可以根据工程规范指标来确定具体哪些工程日志健康度低,然后再根据个体日志规范,来确定具体的不合规或者冗余日志,层层递进,以达到精确定位,准确修改的效果。
3)知识库模块
经过第一步的日志聚合,得到工程级别的聚合结果,由于同一系统下的不同工程可能存在相似的日志,在此我们通过相似度计算,对同一系统下各个工程的日志聚合结果再做进一步聚合,得到最终系统级别的日志聚合。在实践中,我们根据 8 个系统共计约 1000 万条日志进行收敛聚合,经过两次算法聚合收敛后,得到约 2 千条数据,信息降噪比达到 99%,降噪效果明显。对于降噪后的得到的标准日志,由各系统人员针对所属系统的相关日志,进行标记是否关注,并提供异常原因和对应的解决方案,以辅助日志告警和后续的问题解决,以此形成一个可不断迭代更新的日志知识库。
经过标注后的知识库摘要如下所示:
结语
在现今环境下,我们对海量非规范日志主要会遇到日志量巨大且干扰数据多,清洗难度大。针对这些挑战,我们引入模板提取来降低数据量级,通过文本相似度来降低干扰,可以很好的完成日志的收敛聚合。一方面可以很好的辅助进行日志数据治理,另一方面,形成的日志知识库可以帮助日志告警进行辅助决策。
版权声明: 本文为 InfoQ 作者【信仰圣光吧丶】的原创文章。
原文链接:【http://xie.infoq.cn/article/ffd04600d42224972489a2b2a】。文章转载请联系作者。
评论