日志聚类算法 Drain 的实践与改良
在现实场景中,业务程序输出的日志往往规模庞大并且类型纷繁复杂。我们在查询和查看这些日志时,平铺的日志列表会让我们目不暇接,难以快速聚焦找到重要的日志条目。
在观测云中,我们在日志页面提供了聚类分析功能,可以快速聚合相似的日志文本,帮助你全览不同类型的日志。这个功能背后就由基于 Drain 的改良算法驱动。

快速理解 Drain 算法
根据 logparser 项目提供的 Benchmark 数据和论文原文可知,Drain 在一众日志聚类算法中准确度和性能都几乎是最好的,所以我们选择基于 Drain 算法来实现产品功能。

在这里我们尝试根据 Drain 论文来总结和梳理一下算法的主要逻辑:

1、首先对日志进行业务预处理,将一些常见的日志模式替换为占位符,比如时间、用户 ID、IP 等
2、对预处理的数据进行分词,并在 Drain 的搜索树的第一层找到对应单词数量的子节点
3、再逐个根据日志中的单词序列,在下层的前缀搜索树上找到对应的日志聚类桶
4、遍历对应前缀树指向的日志聚类桶,分别判断当前日志跟对应日志类的相似度是否达到阈值
- 相似度算法:两条日志从左往右,一个一个单词看相不相同,统计相同单词的数量,除以日志长度就得到相似度
5、如果相似则将当前的日志加入该类别,不相似则创建新的类别并加入到前缀树中
我们回顾一下上述的处理流程:
1、占位预处理的目标是为了将日志中最常见的变量替换为相同的占位符,来提升相同单词的比例,以提升最终文本的相似度
2、Drain 第一层的按照单词数区分的子树和后续根据前缀树拆分的子树目标都是缩小相似度计算的开销,我们只用跟最可能相似的日志组来对比计算
相信到这里,你已经基本理解了 Drain 算法的基本设计思路。这个算法思路总体并不复杂,固定深度的查找树、简单的相似度匹配算法都让算法的运行非常高效。
改良 1:占位处理后置,并提升处理效率
我们在最初的使用中按照论文的描述给日志增加了一些常见的日志模式占位符,比如:
- 时间:
[0-9]{1,}:[0-9]{1,}:[0-9]{1,}.?[0-9]{1,}? - IPv4:
\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3} - Hex:
0x[a-f0-9A-F]+ - 数字:
-?[0-9]{1,}.?[0-9]* - ID:
[0-9a-f]{4,}
众所周知,时间在日志中输出的格式是可能有非常多种类型的,我这里只添加了最简单的一种,还有 IPv6 因为正则表达式的规则过于复杂也还没加。
在初步添加上述少量的占位符匹配之后,我们就发现 Drain 算法的匹配效率显著下降。
在我们内部一个 1w 行的测试数据集上,完成训练的时间由 80ms 增长到 2.2s,匹配效率降低约 30 倍,通过 CPU Profiler 调用树可以观察到性能的主要开销都在正则表达式的替换上。

那么不进行占位处理可以吗?不可以,这些变量会严重影响日志相似度的判定。
那么可以换更高效的正则表达式库吗?我们尝试了一些常见的优化方案,但提升的幅度没有这么显著。
我们使用多个正则表达式对全部日志的每个单词都进行了一遍正则的匹配,这个的开销自然是不低的。那这个完整的匹配是必须的吗?哪些路径的正则匹配是必须的?
前面我们已经强调过,我们期望的通过占位处理之后不影响日志相似度的判断。那么我们其实只需要在日志相似度运算的时候对必要的单词来做这个正则匹配就好了。
假设当前日志组的模板变量是:Just A Log Template <Number> ,现在我们有一个日志 Just A Log Template 123 需要跟这个模板对比相似度,我们在逐个单词进行对比相似度时,只需要判断日志的最后一个单词是否匹配中 <Number> 占位符对应的正则表达式,我们不用判断这个单词是否能匹配中其他的占位符,也不用关注其他的单词是什么情况,更不必要提前对这个日志进行完整占位处理。
Drain 本身通过多层的分桶降低了我们日志需要判断的聚类组的数量,另外我们根据日志组的模板变量确定了需要进行哪种占位符的判断,所以实际的匹配开销经过这两重剪枝就大大降低了。在刚才提到的数据集下,我们把占位符的匹配后置,完成训练的时间就降低到只有 120ms 左右了。
改良 2:提升占位处理通用性
在通过剪枝解决了匹配效率问题之后我们还关注到当前的占位处理的逻辑其实不太通用,IPv4、IPv6、超多种时间格式、用户自行输出的结构体、JSON 文本等等其实结构非常复杂,根据不同的使用习惯不同也难以罗列完整,维护也比较复杂。
我们最终的方案是尝试将常见的符号比如 :.," 等前后添加空格,在分词时就可以把这些符号拆分成单独的单词,这样比如一个 IPv4 的地址会被拆分为 <Number>:<Number>:<Number>:<Number> ,一个 IPv6 地址会被拆分为 <ID> 和 : 子元素,时间格式会被拆分为数个 <Number> 和 : 。
按这种逻辑,我们最终只维护了三个基本的占位元素,分别是:
- 数字:
[-+]?[0-9]+ - Hex:
0x[a-f0-9A-F]+ - ID:
[a-f0-9A-F]{4,}
这样除了维护更简单,常见的占位格式都不用维护,而且对 JSON 文本的支持也更友好了,可以将其中的 KV 都完全拆分。
改良 3:支持变长日志聚类
回忆一下 Drain 的处理流程,我们在知道日志长度的时候就直接划分子树了。那么显而易见的,Drain 对变长的日志支持效果都不会太好。
举个实际点的例子,两个包含 UA 的请求日志:
1、[28/Aug/2022:07:01:36 +0800] "GET / HTTP/1.1" 200 "Mozilla/5.0 (Linux; Android 12; PEEM00 Build/RKQ1.211119.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/97.0.4692.98 Mobile Safari/537.36"
2、[28/Aug/2022:07:50:18 +0800] "GET / HTTP/1.1" 200 "Mozilla/5.0 (Linux; Android 9; MI 8 Build/PQ3A.190801.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/87.0.4280.101 Mobile Safari/537.36"
这两条日志的长度是不一样的,一个的手机型号是 PEEM00 一个的手机型号是 MI 8 。所以虽然两个日志非常相像,但还是不会被聚合到同一个类别中。
这合理吗?显然是不合理的。
所以我们给 Drain 额外增加了一个相邻长度聚类组的相似度判断逻辑。同时要注意到,之前我们的相似度判断算法是逐个单词匹配的,当这里单词数不一样的时候,中间可能会错位,导致相似度计算可能会很严重偏低,我们原有的算法已经不太适用这种情况了。
常见的文本相似度算法都不限定两个文本单词长度必须相等,比如计算欧几里得距离、曼哈顿距离、明可夫斯基距离、余弦相似度等。这里我们最终选用了 minhash 算法,我们可以提前对每个日志组计算好特征向量,在判断匹配时给日志行计算雅卡尔距离时可以更高效。
同时要注意的是,如果你的数据集是请求日志这样的数据,单词的长度可能都差不多,并且不同的日志组本身的相似度其实已经很高了。这样的数据集下,你不能只优先匹配相邻长度的日志组,应该优先把前后一定长度范围的全部日志组放在一个大池子里来找到最优解。
总结
经过我们对 Drain 的深入剖析和改良,新算法的流程是这样的:
1、直接对日志文本进行分词,并在 Drain 的搜索树的第一层找到对应单词数量的子节点
2、再逐个根据日志中的单词序列,在下层的前缀搜索树上找到对应的日志聚类桶
3、遍历对应前缀树指向的日志聚类桶,分别判断当前日志跟对应日志类的相似度是否达到阈值
- 相似度算法:两条日志从左往右依次对比,如果类别模板中对应位置是占位符,则使用占位符对应的正则表达式匹配原始文本,跟原有算法一样计算相似度
4、如果相似则将当前的日志加入该类别,不相似则拿出来前后一定范围长度的全部日志类别,对比这些日志于当前的日志的 minhash 的笛卡尔距离,判断相似度是否达到阈值
5、如果前面两种相似度判断都失败,则创建新的日志分类,此时注意需要对现有的日志进行完整的占位符替换,最后将创建的新的日志类别加入前缀搜索树中
经过如上的处理流程,该算法对于定长、变长、JSON 等格式的日志聚合表现相比于原版 Drain 都更加优异,同时也能保持极高的匹配效率。
相关文章:
日志聚类算法 Drain 的实践与改良
在现实场景中,业务程序输出的日志往往规模庞大并且类型纷繁复杂。我们在查询和查看这些日志时,平铺的日志列表会让我们目不暇接,难以快速聚焦找到重要的日志条目。 在观测云中,我们在日志页面提供了聚类分析功能,可以…...
如何让用户在网页中填写PDF表格?
在网页中让用户直接填写PDF表格,可以大大简化填写、打印、扫描和提交表单的流程。通过使用复选框、按钮和列表等交互元素,PDF表格不仅让填写过程更高效,还能方便地在电脑或移动设备上访问和提交数据。 以下是在浏览器中显示可填写PDF表单的四…...
GXUOJ-算法-补题:22级《算法设计与分析》第一次课堂练习
2.最大子数组和 问题描述 代码解答 #include<bits/stdc.h> using namespace std; const int N1005; int sum,n,a[N]; int res-1;int result(){for(int i0;i<n;i){if(sum<0) suma[i];else{suma[i];resmax(res,sum);}}return res; } int main(){cin>>n;for(i…...
源代码编译安装X11及相关库、vim,配置vim(3)
一、vim插件安装 首先安装插件管理器Vundle ()。参照官网流程即可。vim的插件管理器有多个,只用Vundle就够了。然后~/.vimrc里写上要安装的插件: filetype offset rtp~/.vim/bundle/Vundle.vim call vundle#begin() Plugin VundleVim/Vundle.vim Plugin powerline…...
uniapp 微信小程序 自定义日历组件
效果图 功能:可以记录当天是否有某些任务或者某些记录 具体使用: 子组件代码 <template><view class"Accumulate"><view class"bx"><view class"bxx"><view class"plank"><…...
EdgeX规则引擎eKuiper
EdgeX 规则引擎eKuiper 一、架构设计 LF Edge eKuiper 是物联网数据分析和流式计算引擎。它是一个通用的边缘计算服务或中间件,为资源有限的边缘网关或设备而设计。 eKuiper 采用 Go 语言编写,其架构如下图所示: eKuiper 是 Golang 实现的轻量级物联网边缘分析、流式处理开源…...
react 优化方案
更详细的 React 优化方案可以分为性能优化、代码结构优化、开发效率提升等多个方面,结合实际项目需求,逐步应用这些优化策略。 一、性能优化 1. 避免不必要的重新渲染 React.memo: 缓存组件,防止组件在父组件重新渲染时无意义的重新渲染。 const ChildComponent = Reac…...
【Linux】sed编辑器
一、基本介绍 sed编辑器也叫流编辑器(stream editor),它是根据事先设计好得一组规则编辑数据流。 交互式文本编辑器(如Vim)中,可以用键盘命令交互式地插入、删除或替换文本数据。 sed编辑器是根据命令处理…...
(leetcode算法题)137. 只出现一次的数字 II
处理这种数据集中只有一个数出现的频次为1,其他数出现的频次均为k的题目 往往都是使用位运算的进行求解 假设 target在数据集中只出现了1次,其他数据n1, ... nj都出现了 k 次, 考虑数据集中所有数据的第 i 位的取值,那么将会有…...
在大数据环境下高效运用NoSQL与关系型数据库的结合策略
在大数据环境下,高效运用NoSQL与关系型数据库结合策略涉及到理解两者各自的优劣势,以及如何有效地整合它们。以下是一些代码示例和实际案例,以帮助你了解这种结合策略。 背景介绍 NoSQL数据库通常用于处理大量非结构化或半结构化的数据&…...
C语言——分支与循环语句
目录 一.分支语句 1.if语句 2.悬空else问题 3.switch语句 default子句 二.循环语句 1.while循环 whle循环流程图: break与continue 2.for循环 2.2for与while循环 2.3关于for循环的一道笔试题 3.do while 循环 三.猜数字游戏实现 四.goto语句 补充 …...
下载b站高清视频
需要使用的edge上的一个扩展插件,所以选择使用edge浏览器。 1、在edge浏览器上下载 强力视频下载合并 扩展插件 2、在edge上打开b站,登录自己账号(登录后才能下载到高清!!)。打开一个视频,选择自…...
常见 JVM垃圾回收器、内存分配策略、JVM调优
垃圾收集( Garbage Collection ,下文简称 GC),垃圾收集的历史远远比 Java久远。经过半个世纪的发展,今天的内存动态分配与内存回收技术已经相当成熟,一切看起来都进入了“自动化”时代,那为什么…...
【HarmonyOS应用开发——ArkTS语言】欢迎界面(启动加载页)的实现【合集】
目录 😋环境配置:华为HarmonyOS开发者 📺演示效果: 📖实验步骤及方法: 一、在media文件夹中添加想要使用的图片素材 二、在entry/src/main/ets/page目录下创建Welcome.ets文件 1. 整体结构与组件声…...
【MySQL】:Linux 环境下 MySQL 使用全攻略
📃个人主页:island1314 🔥个人专栏:MySQL学习 ⛺️ 欢迎关注:👍点赞 👂🏽留言 😍收藏 💞 💞 💞 1. 背景 🚀 世界上主…...
Linux驱动开发 gpio_get_value读取输出io的电平返回值一直为0的问题
当时gpio子系统进行读取时返回必定是0 因此,首先必须使用platform驱动来管理gpio和pinctrl子系统,然后如果按照正点原子所教的设备树引脚设置为0x10B0则会导致读取到的电平值为0。 解决方法: 将设备树中的引脚设置为 pinctrl_gpioled: gpio…...
【数据结构】栈与队列(FIFO)
在阅读该篇文章之前,可以先了解一下堆栈寄存器和栈帧的运作原理:<【操作系统】堆栈寄存器sp详解以及栈帧>。 栈(FILO) 特性: 栈区的存储遵循着先进后出的原则。 例子: 枪的弹夹,最先装进去的子弹最后射出来,最后装入的子弹…...
vue.js -ref和$refs获取dom和组件
在Vue.js中,ref和$refs是两个常用的属性,用于访问DOM元素和组件实例。下面分别详细解析这两个属性,并提供代码实例。 ref属性 ref属性用于给DOM元素或组件指定一个唯一的引用标识,在Vue实例中可以通过这个标识来访问对应的DOM元素…...
unity学习5:创建一个自己的3D项目
目录 1 在unity里创建1个3D项目 1.1 关于选择universal 3d,built-in render pipeline的区别 1.2 创建1个universal 3d项目 2 打开3D项目 2.1 准备操作面板:操作界面 layout,可以随意更换 2.2 先收集资源:打开 window的 AssetStore 下载…...
IEEE PDF eXpress遇到Font TimesNewRomanPSMT is not embedded的解决方案
IEEE PDF eXpress遇到Font TimesNewRomanPSMT is not embedded的解决方案 问题描述 在IEEE PDF eXpress上上传论文后,出现Font XXX is not embedded的问题。 该问题是指你所插入的图片等,没有将对应的字体嵌入进去。 解决方案 以下以Origin Lab图片…...
大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
倒装芯片凸点成型工艺
UBM(Under Bump Metallization)与Bump(焊球)形成工艺流程。我们可以将整张流程图分为三大阶段来理解: 🔧 一、UBM(Under Bump Metallization)工艺流程(黄色区域ÿ…...
客户案例 | 短视频点播企业海外视频加速与成本优化:MediaPackage+Cloudfront 技术重构实践
01技术背景与业务挑战 某短视频点播企业深耕国内用户市场,但其后台应用系统部署于东南亚印尼 IDC 机房。 随着业务规模扩大,传统架构已较难满足当前企业发展的需求,企业面临着三重挑战: ① 业务:国内用户访问海外服…...
Python学习(8) ----- Python的类与对象
Python 中的类(Class)与对象(Object)是面向对象编程(OOP)的核心。我们可以通过“类是模板,对象是实例”来理解它们的关系。 🧱 一句话理解: 类就像“图纸”,对…...
起重机起升机构的安全装置有哪些?
起重机起升机构的安全装置是保障吊装作业安全的关键部件,主要用于防止超载、失控、断绳等危险情况。以下是常见的安全装置及其功能和原理: 一、超载保护装置(核心安全装置) 1. 起重量限制器 功能:实时监测起升载荷&a…...
