在软件研发过程中,构建日志、系统日志和异常日志往往数量庞大,给开发者排查问题带来很高成本。如何利用机器学习改善开发者体验,减少无效排查时间,是许多技术团队正在探索的重要方向。本文将介绍一种结合神经嵌入与局部敏感哈希(LSH)的日志分析方法,用于提升语义差异比较和日志异常检测的效率。

想象一下,你需要在一份失败的软件构建日志中排查错误或回归问题。这份日志足有 2.5GB,约 300 万行,而真正的问题可能隐藏在第 100 万行附近。这样的工作量,几乎不可能依靠人工完成。
一个相对巧妙的办法是:将失败构建的日志行与最近一次成功构建的日志行进行比较,期望错误能以某些“不寻常”的日志行形式暴露出来。
传统的 MD5 差异比较速度很快,但由于它会捕捉行与行之间字符级别的差异,最终仍可能产生至少数十万行候选内容,需要工程师逐一排查。使用机器学习中的 k 近邻聚类进行模糊差异比较,例如某些日志归约工具采用的方法,可以将候选内容减少到大约 4 万行,但处理时间大约需要 1 小时。
我们的方案只需约 20 分钟计算时间,就能将候选内容进一步减少到约 2 万行。更重要的是,得益于开源生态,这套方案只需要约 100 行 Python 代码即可实现。
这项应用结合了两类技术:神经嵌入和局部敏感哈希(Locality-Sensitive Hashing,LSH)。神经嵌入用于编码词语和句子的语义信息;局部敏感哈希则能高效地把距离较近的对象分到同一个桶中,把距离较远的对象分到不同桶中。将嵌入与 LSH 结合起来,是一种非常适合日志分析和语义差异比较的技术思路。
在企业内部落地这类开发者体验优化实践时,技术能力之外,还需要把需求、开发、测试、发布、知识沉淀和效能数据串联起来。比如 PingCode 这类智能化研发管理工具,可以帮助团队将研发过程自动化、数据化、智能化,让日志分析、缺陷定位、需求流转和经验沉淀形成更完整的研发效能闭环。
注:我们使用某开源深度学习框架的 2.2 版本在 CPU 上进行迁移学习,并启用了即时执行模式;k 近邻算法使用某开源机器学习库中的 NearestNeighbors 实现。对于基于模型的最近邻搜索,也有一些更先进的近似最近邻算法实现,可能更适合特定场景。
什么是神经嵌入?为什么它能改善日志分析?
构建 k-hot 词袋模型,是解决非结构化或半结构化文本去重、搜索和相似性问题时,一个典型而实用的起点。词袋编码类似于一个字典,记录每个词及其出现次数。以下是句子 “log in error, check log” 的词袋表示:{“log”: 2, “in”: 1, “error”: 1, “check”: 1}
这种编码也可以表示为向量:每个索引对应一个词,索引处的值表示该词出现的次数。例如,“log in error, check log” 可以表示为:[2, 1, 1, 1, 0, 0, 0, 0, 0, …]
请注意,这个向量中包含大量的零。值为零的条目代表词典中所有没有出现在该句子里的词。向量可能包含的条目总数,也就是向量维度,取决于所用语言词典的大小,通常可达数百万甚至更多。当然,通过一些巧妙的技巧,也可以将维度降低到几十万。
现在再看短语 “problem authenticating” 的字典和向量表示。它与前一个句子在词面上完全没有重合:{“problem”: 1, “authenticating”: 1} [0, 0, 0, 0, 1, 1, 0, 0, 0, …]
这两个表达在语义上是相近的,也就是说,它们表达的意思基本相同;但从词汇层面看,它们又截然不同,没有共享任何词。在模糊差异比较场景中,我们可能希望判断这两句话“语义上过于相似,不值得单独高亮”。然而,MD5 比较和基于 k-hot 词袋编码的 kNN 方法,都无法很好地做到这一点。
降维技术可以借助线性代数或人工神经网络,将语义相近的词语、句子和日志语句映射到新的向量空间中,使它们在这个空间里彼此靠近。这种表示方法就称为“嵌入”。在日志分析场景中,神经嵌入能够帮助系统识别“表达不同但含义接近”的日志内容。
在我们的例子中,“log in error, check log” 可能对应一个五维嵌入向量:[0.1, 0.3, -0.5, -0.7, 0.2]
而 “problem authenticating” 可能对应:[0.1, 0.35, -0.5, -0.7, 0.2]
在余弦相似度等距离度量下,这两个嵌入向量彼此非常接近;这与它们在 k-hot 词袋向量中的表现截然不同。对于构建日志或系统日志这类短文本而言,低维、稠密的表示非常有用。
在实际应用中,我们可以用 100 个信息密度更高的嵌入维度,取代原本数千甚至更多的词典维度。当前较先进的降维方法包括对词共现矩阵进行奇异值分解的 GloVe,以及专门设计的神经网络模型,如 word2vec、BERT 和 ELMo。
如何用 LSH 提升构建日志的语义差异比较效率?
在一家海外流媒体公司的技术团队内部,有这样一个玩笑:这家公司主要负责生成日志,偶尔顺便播放视频。玩笑背后,其实是严肃的工程现实。在异常监控、日志处理和流处理等领域,系统每秒都要处理数十万个请求。如果希望把机器学习应用到遥测和日志系统中,扩展自然语言处理(NLP)方案就是必不可少的一步。
正因如此,我们非常重视文本去重、语义相似搜索和文本异常值检测能力的扩展。对于需要实时解决的业务问题而言,这并不是锦上添花,而是必要能力。
我们的差异比较方案包括几个步骤:首先,将每一行日志嵌入到一个低维向量中,并可选择同时对嵌入模型进行微调或更新;然后,将这些向量分配到不同簇中;最后,把落在不同簇中的日志行识别为“不同”的内容。局部敏感哈希是一种概率算法,它可以在常数时间内完成簇分配,并以接近常数时间的效率完成最近邻搜索。
LSH 的工作原理,是将向量表示映射为标量;更准确地说,是映射为一组标量。标准哈希算法的目标,是尽量避免不同输入之间发生冲突;而 LSH 的目标则不同:它希望距离较远的输入尽量不要发生冲突,同时鼓励向量空间中彼此接近、但并不完全相同的输入发生冲突。
例如,“log in error, check log” 的嵌入向量可能被映射为二进制数 01,而 01 就代表某个聚类。“problem authenticating” 的嵌入向量也很可能被映射到同一个二进制数 01。这就是 LSH 实现模糊匹配,以及它的反向任务——模糊差异匹配——的基本原理。
LSH 的早期应用主要集中在高维词袋向量空间中。我们当时认为,它同样可以有效应用于嵌入空间;也有迹象表明,其他研究者同样意识到了这一点。
我们利用 LSH 和神经嵌入技术,对构建日志进行文本异常值检测。现在,工程师只需查看日志中的一小部分内容,就能识别并修复可能影响关键业务软件的问题。同时,这套方法也让我们能够对几乎任意日志行进行实时语义聚类。
如今,我们已经将语义 LSH 的优势应用到了该技术团队的每一次构建中。语义能力让我们能够根据含义对表面上不同的日志项进行分组,并在异常值报告中突出显示真正值得关注的内容。
机器学习改善开发者体验的几个实践效果
下面是一个典型的语义差异比较示例:原本需要查看 6,892 行日志,最终只需关注 3 行。
另一个例子中,构建过程生成了 6,044 行日志,但报告中只保留了 171 行。主要问题几乎立刻就能在第 4,036 行附近显现出来。
换句话说,工程师只需快速阅读 171 行,而不是 6,044 行。
回到文章开头的问题:为什么一次构建会产生如此庞大的日志?
原因是,技术团队内部有数千个构建作业。其中一些作业会对消费电子设备进行压力测试,而这些测试在跟踪模式下运行。它们产生的数据量极其庞大,如果不进行任何预处理,就很难直接分析。
即使在日志规模相对较小的情况下,这套方法也能将 91,366 行日志压缩到 455 行,显著降低排查难度:压缩比:91,366 / 455 = 200 倍
也就是说,工程师只需快速阅读 455 行,而不是 91,366 行。
除此之外,我们还在不同框架、编程语言和构建场景中,看到了许多语义差异比较的成功案例。这说明,机器学习不仅可以用于推荐、搜索和预测,也可以直接用于优化软件研发流程,提升开发者体验。
结语:机器学习正在成为开发者体验优化的重要工具
开源迁移学习数据产品和 SDK 的成熟,让我们能够用极少量代码,通过 LSH 算法解决语义最近邻搜索问题。我们尤其感兴趣的是,迁移学习和微调究竟能为应用带来哪些独特优势。
我们很高兴有机会解决这类问题,并帮助工程师更高效、更快速地完成工作。
这类实践也说明,机器学习并不只适用于面向终端用户的推荐、搜索或预测场景。它同样可以深入软件工程流程本身,成为改善开发者体验的重要工具。通过更智能地处理日志、识别异常和发现差异,机器学习能够减少重复劳动,缩短问题定位时间,让开发者把精力更多投入到真正有价值的工程判断和系统改进中。
而当这类优化从单个工程团队扩展到跨部门协作时,除了研发管理工具,团队还需要更通用的项目协作能力。比如 Worktile 这类项目协作系统,可以承接任务、项目、文档、目标、日历和审批等协作场景,帮助不同角色围绕同一个研发目标高效配合。
文章包含AI辅助创作:用机器学习改善开发者体验:日志分析与语义差异比较实践,发布者:shang,转载请注明出处:https://worktile.com/kb/p/3979939
微信扫一扫
支付宝扫一扫