日志聚类:Drain3和Spell算法简单了解

前言

日志聚类主要在智能运维场景中用的比较多,比如异常检测告警,告警合并,日志类型统计,安全场景下的入侵检测,日志统计分析,数据挖掘等方面。业内厂商做的好的有阿里的LogReduce,腾讯日志聚类,华为日志聚类等。

思路

1,日志聚类的前提是:同一个服务下,一个日志模板产生的日志经过分词得到的词的个数是相同的
2,日志聚类的过程就是对日志数据进行模板(Pattern)的提取和匹配,而不像机器学习中的聚类过程。因此不用涉及到复杂的自然语言处理(NLP),如果是自然语言处理主题分类则存在数据清洗->分词处理->文本转向量->PCA降维->k-means聚类等过程。那将非常复杂,且计算和开发成本将非常高。
3,在如果不满足第一点的情况下,如果分词长度不一样将如何处理?
4,日志数据是实时的,能不断增量更新模板(Pattern),因此无法使用k-means聚类等离线算法。

聚类流程

业内主要的日志聚类解决方案主要实现是使用Drain3和Spell算法。Drain3一般做第一层的分类长度相等的聚类过程,Spell主要做分类长度不相等的二次聚类过程

image.png

主要思路
1,数据采集到消息队列中。
2,日志数据进入聚类引擎后,首先通过Drain3做一次聚类,spell做二次聚类。
3,聚类完成后将原始日志和特征值一起存储到日志行中。
4,聚类完成后同时将聚类模板(Pattern)数据写到第三方的存储中。

Drain3算法

Drain算法由香港中文大学提出《Drain An Online Log Parsing Approach with Fixed Depth Tree》并提供了一个python实现的demo,Drain3在Drain的基础上主要是为中文提供了解决方案,整体思路和Drain基本一致。其核心思想是使用一个固定深度的Parser Tree,提供了实时增量提取日志模板的能力。

image.png

树结构说明:
1)第一层是 root node,无业务意义;
2)第二层是分词后词的个数,通常分词符号可以按自己定义比如(,#$|等),如果是中文的话需要单独的分词器,分词数组长度Length。
3)第三层及以下是日志模板中的前缀单词。一般情况下不会超过4层,且为了避免子节点爆炸,会设置一个maxChild,超过这个节点数值的全部标识为*。
4)最底层的叶子节点为相同前缀单词的日志模板。
5)树的所有深度都一致。

聚类流程

1,Preprocess by Domain Knowledge (领域知识处理)
之前说过,使用同一个日志模板打印出的日志,同一个分词器下,分词后长度是一致的。因此可以把这个模板区分变量和常量,变量使用*代替,常量直接显示,然后组成一个模板。而Drain3就是推导这样一个模板汇聚的过程。


image.png

那反过来如何将变量提取出来呢,这个时候就可以把那些比如:数值,IP,时间,邮件等使用正则提取出来即可,然后组成预处理后的日志。比如论文中的例子。

#原始日志
PacketResponder 0 for block blk_4003 terminating
#领域处理后的(正则处理)
PacketResponder * for block * terminating

像官方demo就提供了一个这样的领域知识提取配置正则的地方。

image.png

2,Search by Log Message Length(通过日志长度搜索树)
通过分词获得数组长度即为日志长度,比如论文中的原始日志"Send block 44",分词获得["Send","block","44"],经过第一步领域只是出来后变成["Send","block","*"],Length为3。获得Length后即可遍历Parser Tree匹配第2层节点。

3,Search by Preceding Tokens (通过前缀词搜索树)
上一步获得的分词数组["Send","block","44"],遍历到第3到depth-1层,判断是否命中节点。

4,Search by Token Similarity(通过词的相似度匹配)
由于之前的步骤已经将Length和前缀树都匹配成功了,则后面需要匹配叶子节点中日志组的相似度。匹配算法如下


image.png
image.png
image.png
image.png

由于之前的前提是分词后的长度一致,因此n是一样的。通过两个数组的对比,计算函数simSeq如果>=我们设置的st(相似度)则表示当前日志组为最近匹配,否则返回么有匹配到。

5,Update the Parse Tree (更新树)
考虑到日志是实时增量的,需要不断更新树。然后通过大量的数据聚类出一个统一的模板,但是如果是同一个服务同一个日志模板,基本上前缀单词节点数是不会很大的,如果超过了为了避免子节点爆炸,超过maxChild的模板均使用*作为前缀单词。那是如何更新的呢。

image.png

主要思路举例
a,原始日志"Send block 44",分词获得["Send","block","44"],经过第一步领域只是出来后变成["Send","block","*"],Length为3。
b,构架图中的左边的Parser Tree,第2层为字符串长度,第3和4层作为字符串前缀节点,底层叶子节点保存Log Group,Log Group存在两个数据结构Ids和LogEvent,分别保存聚类后的日志唯一ID数组和模板Pattern。
c,来了新的日志"Receive 120 bytes",首先对字符串分词获得["Receive","120","bytes"],Length为3。
d,匹配到了第二层节点,匹配第三层节点前缀词为send,不匹配则创建一个新的子节点。
e,将日志ID保存到叶子节点中的Log Group Ids中,模板Pattern保存到LogEvent中,完成更新。

Spell算法

Spell由犹他大学大名鼎鼎的李飞飞大佬提出,且思想相对于Drain更容易理解。前面说过Drain主要是为了同一个日志模板相似度分析的情况。那如果分词长度不一样那该怎么样获得聚类模板呢,Spell算法:《Spell: Streaming Parsing of System Event Logs》。一般情况下同一个日志流程中日志模板都是一致的,只有很少的情况下才会出现不一样的日志模板,因此一般Spell做第二层聚合。

各类算法性能对比

image.png

Drain论文中Spell和Drain都是一样的实时增量聚类算法,性能相对于Drain只差一点点,可以看出在不同日志类型下Spell和Drain耗时不分伯仲。

算法思想

Spell核心思想为最长公共子串LCS

image.png

何为最长公共子串LCS(longest common subsequence)?论文中的例子:
image.png

对于数组A:{1,3,5,7,9},数组B:{1,5,7,19},数组A和B的最长公共子串为{1,5,7}。同理对于文本内容数组也是如此。

算法实现思路

image.png

论文例子思路
1)定义两个数据结构LCSObject 和 LCSMap。LCSObject 包括两个数据LCSseq(日志键)和lineIds(日志唯一ID列表),LCSMap用于保存LCSObject
2)用论文中的例子来说明,首先接受到日志"Temperature (41C) exceeds warning threshold",包装成LCSObject 后写入LCSMap中。
3)又来了一个日志"Temperature (43C) exceeds warning threshold",与LCSMap中之前的日志"Temperature (41C) exceeds warning threshold"对比,求出公共子串"Temperature exceeds warning threshold"。
4)判断当最大公共子序列的长度在输入条目长度的1/2倍到1倍之间时,当然这个值可以配置如Drain算法中的st值,合并并且将非公共子串中的词(Token)转换成"*"。

image.png

image.png

5)继续以上步骤,则可以实时增量获得模板。
6)不过当LCSMap越来越大的时候,且日志长度很长的时候,性能会比较差,论文中建议使用前缀树来优化性能,具体的可以查看源论文。

总结

Drain3和spell都是实时增量聚类算法。在同一个日志模板下分词后的长度一致,可以使用drain算法做第一次聚类,在碰到不一样的分词长度的情况下可以使用spell算法做二次聚类。不过由于都存储一个分词过程,因此在中文情况下需要单独考虑,文章只做一个简单的论文学习,具体的细节可以自行查看论文。

参考文档

https://jiemingzhu.github.io/pub/pjhe_icws2017.pdf
https://github.com/logpai/Drain3
https://users.cs.utah.edu/~lifeifei/papers/spell.pdf

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容