UniParser:异构日志数据的统一日志解析器

摘要

日志为大规模在线业务系统的故障诊断提供了第一手信息。日志解析将半结构化的原始日志消息转换为结构化数据,是自动化日志分析(如日志异常检测和诊断)的前提条件。几乎所有现有的日志解析器都遵循将公共部分提取为模板,将动态部分提取为参数的一般思想。但这些日志解析方法往往忽略了日志消息的语义。而且各种日志源间的高度多样性也阻碍了跨不同系统进行日志解析的泛化。本文提出UniParser,从异构日志数据中捕获常见的日志记录行为。UniParser利用Token Encoder模块和Context Encoder模块从日志标记及其邻近上下文学习模式。上下文相似度模块是专门设计来建模学习模式的共性的。在16个公共日志数据集上进行实验,表明UniParser的性能大大优于最先进的日志解析器。

介绍

在实践中,硬件或软件故障是不可避免的,导致服务中断。一旦出现故障,操作人员和开发人员倾向于检查记录系统事件和运行时状态的控制台日志,及时调查、缓解和解决故障。面对原始日志消息量的快速增长,从巨大的日志数据中识别有价值的信息变得越来越具有挑战性,为了解决这一问题,自动化日志分析通过机器学习(ML)或深度学习(DL)技术自动分析日志数据。

典型的日志分析场景包括基于日志的异常检测、诊断、故障预测和性能建模。重要的第一步是日志解析,将半结构化的控制台日志解析为结构化的格式。日志解析后,将结构化的日志数据输入各种ML或DL模型分析。

如上图,在软件执行过程中,日志由源代码中的各种日志语句生成,并以交错的方式收集。典型的日志包括日志头(如时间、级别)和日志消息,日志消息还包括两个元素:

1)固定在源代码中的静态描述性单词,用于表示系统事件,即日志模板。例如,"SessionID=<*>, initialized by <*>, version (<*>).";

2)动态变量, 反映系统运行时状态,随着不同的执行而变化,称为日志参数。例如," 30546173","OSAgent"和" 1.0.0"是由三个不同的变量生成的参数。日志解析的目标是从原始日志消息中提取静态日志模板和动态日志参数。

日志解析的一种简单的方法是将日志与源代码匹配。由于该方法在处理不同的日志格式时是特别的和标签密集的,因此在实际中并不适用。且源代码经常不可用。另一种方法是根据生成的日志数据手工设计正则表达式,但存在可扩展性差、精度低等问题。

日志解析器:不随日志消息变化的标记(例如,"SessionID=", "Starting")是模板,而相反的标记(例如,"592","1612","660")是日志参数。利用各种统计分析(例如,前缀树)和数据挖掘技术(例如,频繁模式挖掘和聚类)从原始日志消息中提取公共部分。

现有的日志解析器的精度仍不理想,会对后续基于日志的异常检测等任务造成严重影响。导致错误解析结果的两个主要问题:

1)现有的日志解析器仅依赖关于提取常见部分作为模板而忽略日志的语义意义。如上图,如果考虑日志的语义,应该将目录地址“/etc/data”和返回状态“success”标识为参数。"/etc/data"是默认配置的数据读取目录,"success"表示正常的系统行为,这两者在日志消息中不会经常被更改。因此,在不考虑语义的情况下,现有日志解析器会错误地将两个参数都视为模板。

2)日志来自不同业务和系统的内容具有高度的多样性。不同数据源产生的日志中使用的系统事件和单词是非常不同的。例如,只有大约0.5%的日志令牌在三个不同操作系统平台(Linux、Windows和Mac)生成的日志源之间共享。这阻碍了跨异构日志数据源的日志解析的通用性。面对新的日志源,必须重新积累足够的原始日志数据作为训练材料,调整超参数以适应新的日志源,重新配置正则表达式进行预处理,甚至构建一个全新的日志解析器。

对上述问题,本文指出了日志数据的一个重要但特殊的特征,即无论日志内容如何,都存在共同的语义模式来表示模板或参数。这是因为开发人员倾向于遵循常见的日志记录实践以提高可读性。例如,开发人员习惯将参数嵌套在括号中(例如,"(1.0.0)"),或者按照惯例将返回状态(例如,"success")设置为参数。为了捕获在大多数日志数据源中普遍存在的这种模式,本文提出了一个跨多个日志源训练的统一日志解析器,UniParser。由三个模块组成。令牌编码器模块和上下文编码器模块负责从日志标记本身及其邻近的上下文学习语义模式。上下文相似度模块使模型关注已学习模式的共性。经过训练后,UniParser可以直接应用于新的日志数据源。

主要贡献:

提出UniParser,统一的日志解析器,可以跨异构日志源捕获模板或参数的公共模式。在16个基准日志数据集上评估,UniParser比所有现有方法的性能都要好得多。通过实验验证了该方法的有效性和模块有效性。

背景

日志解析

日志解析的目标是从原始日志消息中提取静态日志模板部分和动态日志参数部分。开发人员编写的自由文本日志,这些日志由一些静态的描述性单词(日志模板)和一些在软件运行期间将填充在日志模板中的动态变量(日志参数)组成。"2021-0928 04:31:30 DEBUG"是日志头,通常很容易提取,因为它的格式在特定的日志源中是固定的。“SessionID=<*>, initialized by <*>, version(<*>)”是日志模板,“30546173”、“OSAgent”和“1.0.0”是填充到模板占位符中的日志参数,用于形成完整的日志消息。

现有解析器

现有的日志解析器都遵循以下核心思想:提取原始日志消息的公共部分作为日志模板,其余部分作为日志参数处理。如上图所示,先将一系列相似的日志分组在一起,发现在这些日志中有一些日志标记频繁且广泛地出现,如“SessionID”、“initialized”、“by”,将这些日志标记标识为日志模板部分。其他在不同日志消息中变化的令牌被视为日志参数,如“OSAgent”、“NetAgent”和“PerfCounter”。

频繁模式挖掘:日志的公共部分应该在整个日志数据集中频繁出现,因此在日志解析任务中得到了广泛的应用。首先遍历日志信息,基于标记、标记位置对或标记n-grams构建频繁项集,给定频繁的项集,将日志消息分组到几个集群中,并从集群中提取日志模板。SLCT是第一个将频繁模式挖掘应用于日志解析[30]的工作。LFA进一步考虑了令牌频率分布。LogCluster在频繁项挖掘过程中考虑令牌位置。Logram旨在提取那些频繁的2克和3克的日志标记,而不是基于单个标记。

Clustering:为了捕获日志的公共部分,可将类似的日志聚集在一起,并将每个集群中共享的公共标记标识为模板。与常用的模式挖掘方法相比,这种方法可以在相似日志的局部集群上进行共性部分提取,而不是对全局日志数据集进行提取。如,LKE和LogMine利用分层聚类算法,基于加权编辑距离对相似日志进行分组。与直接对原始日志消息进行聚类不同,LogSig首先提取日志的签名,然后对其进行聚类。SHISO和LenMa都是在线日志解析方法,这意味着它们能够以流的方式逐个处理日志消息,这在现实场景中更实用。两个日志解析器都使用增量集群技术的思想。

启发式:日志消息有一些独特的特征。一些日志解析器利用提取公共部分作为模板。AEL通过比较常量令牌和变量令牌之间的发生情况,将日志消息分成多个组。IPLOM采用迭代分区策略,该策略根据消息长度、令牌位置和映射关系将日志消息划分为组。Drain使用前缀树的思想。构建一个固定深度的树结构来表示日志消息,并有效地提取常用模板。Spell是用最长公共子序列算法流式解析日志。

现有方法的不足

现有的日志解析器在公共数据集中取得了良好的性能,但这些方法在现实场景中仍然很少应用。背后的原因在于它们对复杂的真实日志数据的解析精度不令人满意。导致解析结果不准确的三个主要问题,从根本上挑战当前的日志解析范式。

忽略日志标记的语义意义:现有的日志解析器只考虑了日志的静态和动态属性,忽略了日志的语义。经常导致日志参数和模板的不合理的错误识别。在上图中,一些日志标记(如“success”和“/etc/data/”)属于日志模板的一部分,在不同的日志消息中没有变化。如果考虑到语义,这些标记应该被归类为参数。

不同日志源之间的屏障:不同系统或服务的日志内容具有高度的多样性。例如Windows3、Mac和Linux.系统日志只共享约0.5%的公共日志令牌。例如,“用户新闻的会话由(uid=0)打开”(从Linux日志)和“会话:30546173_4261722401初始化由客户端WindowsUpdateAgent。”(来自Windows日志)是完全不同的日志事件,两者之间只有一个词“session”共享。不同日志源之间的高度多样性阻碍了日志解析器在不同系统或服务之间的泛化。将现有的方法应用到一个新的日志数据源时必须重新积累足够的原始日志数据作为训练材料,调整超参数以适应新的日志源,并重新配置正则表达式进行预处理。对于在线日志解析器需要从头训练。

评价指标不合理:日志模板和参数识别应一视同仁。例如,大多数日志异常检测模型(如LogRobust)使用相同的预测日志模板对日志进行分组,并表示为日志事件,根据这些日志事件识别异常行为。另一方面,一些基于日志的异常检测模型,如DeepLog更注重参数变化,如运行时间或返回状态码。在评估过程中,评估指标衡量分组日志的准确性,但不显式检查提取的模板和参数。因此不能反映日志解析器的有效性。

对上述三个问题,通过对公共日志数据集和工业日志的的调查,发现了日志数据的一个重要特征,即,尽管在不同的系统或服务中日志内容非常不同,但通常遵循某种常见的日志操作。开发人员可能打印不同的日志内容,但有一些共同的日志首选项,对上图中示例,开发人员喜欢将参数嵌套在括号中(“version(1.0.0)”)或将其放在等号后面(“SessionID=30546173”),开发人员还会按照惯例将状态代码(“success”)或目录路径(“/etc/data/”)设置为参数,而不是将其固定为模板的一部分。实际上,还有许多统一的、通用的日志记录规范和实践,这些规范和实践使日志的信息量更大。公共日志记录实践揭示了跨异构日志源捕获公共日志记录行为的机会。能够通过获取常规日志“语法”来区分参数或模板。为了捕获跨异构日志源共享的公共日志记录行为,需要开发新的日志解析器,通过理解日志的语义来学习公共日志记录实践。学习到的模型可以应用于解析新的日志消息源。

UniParser

将日志解析任务转化为日志token分类问题。

假设原始日志消息L在分词后包含n个标记,表示为[t1, t2,…tn]。UniParser根据学习到的常见日志模式来预测每个日志标记ti属于模板部分(yi = 0)还是参数部分(yi = 1)。所有yi = 0的令牌都包含在日志模板中,其他yi = 1的令牌则放入参数列表中。

如上图,所提出的UniParser模型有两个阶段,即离线跨源训练阶段和目标日志源上的在线解析阶段。在训练阶段,将来自多个源的标记日志数据作为训练数据集,将其输入UniParser模型进行训练。模型学习底层的公共模式,指示模板或参数,而不是单独的和特定的日志内容(训练学习一个二分类器)。因此使用多个日志源作为训练集,并提出了一个定制的深度学习模型。

在跨异构日志源进行训练之后,将训练过的模型直接应用于目标日志源进行解析。并行预测每个日志令牌的类(模板或参数),然后将它们分别集成为日志模板或参数列表。

训练日志源和测试日志源可以完全互斥。UniParser为捕获通用语义模式设计了深度学习模型,通过通用语义模式,UniParser可以将从其他日志源学到的知识泛化到未知的新日志源。UniParser不需要解析目标日志源中的任何标签。

模型结构

如下图,UniParser由三个组件组成:Token Encoder模块、Context Encoder模块和Context Similarity模块。

 token编码器模块

给定一个原始日志,首先分词,Token Encoder模块将每个拆分日志标记编码为高维嵌入向量作为模型输入。日志词的多样性和动态性给词向量带来了障碍。日志标记会导致词汇表不足(OOV)问题。开发人员可以创造无限多种的变量名、缩写或特殊技术术语,它们远远超出了常见英语单词的规模,将使词汇量暴增。此外,一些由数字(如"30546173")或一些特殊符号(如" /etc/data/")组成的参数也很难嵌入,因为它们在不断变化。

可以使用字符级嵌入来编码日志标记。字符级的粒度比令牌级的粒度要细。最常用的字符,如小写字母、大写字母、数字、标点符号等(总共使用了96个字符)足以涵盖由它们的组合形成的大多数标记。不在令牌级维护巨大的词汇表,建立一个嵌入层来编码每个字符,然后在一个日志标记中把所有的char级嵌入向量相加,作为它的编码向量。这样既可以避免OOV问题,又可以将嵌入矩阵的大小控制在合适的尺度上。

上下文编码器模块

目标日志标记的类别(模板或参数)不仅与自身相关,还与相邻标记相关,即上下文。一方面,参数倾向于与一些特殊的字符或符号联合出现。对于图1所示的例子,“30546173”在等号“=”的后面,或者“1.0.0”被括号(“(1.0.0)”)括起来。另一方面,上下文的语义也有利于指示参数或模板。图1的第3行说明了一个更复杂的情况。如果我们对仅根据日志标记“/etc/data/”本身确定日志标记的类别没有信心,那么它的上下文“from”有助于将其归类为参数,因为考虑到其语义,“from”后面很可能跟着一个参数(例如目录地址)。

基于上述思想,利用Context Encoder模块对上下文信息进行编码。并非日志消息中的每个日志标记都应该被视为目标日志标记的上下文。这是因为那些远离目标标记的日志标记对于分类来说往往是无用的。例如,在图1的第1行中,顶部令牌“SessionID”与尾部令牌“(1.0.0)”的相关性很小。将目标令牌周围从左k到右k个令牌的范围视为其上下文。一般来说,k = 3的Token Encoder模块将每个上下文标记转换为一个嵌入向量,并获得一个上下文向量序列。目标令牌在此过程中被屏蔽。该操作的目的是希望Context Encoder模块能够独立捕获上下文标记所反映的模式,而不需要目标日志标记本身的帮助。否则模型可能严重偏向于目标日志标记,无法从上下文中学习模式。将上下文向量序列输入双向LSTM网络,获取订单信息。将LSTM中各个时刻的隐藏状态hi聚合为上下文的最终编码向量。

上下文相似度模块

如果Context Encoder模块产生的嵌入向量对应的日志上下文包含类似的模式,它们应该是接近的。常见的模式往往通过不同的日志内容表现出来。char级嵌入是内容感知的,由于上下文中的字符可能是各种各样的,因此会导致编码向量的分散。对于图1的实例,当目标预测令牌“initialized”的类时,其第一行的上下文“by OSAgent”和第2行的“by perfCounter”是非常不同的。他们的编码向量也可能变化很大,不利于模型捕获日志中的通用模式。为了克服这个问题,需要将类似模式下的日志上下文映射到一个更紧密的向量空间,以减轻内容多样性的影响。假设相似的日志消息应该具有相似的模式。因此可以通过相似或不同的日志消息之间的对比学习来指导Context Encoder模块。

为了获得相似的日志消息,首先将来自异构日志源的训练日志数据聚类到几个组中,每组中的日志在令牌长度和第一个令牌上是相同的。同一组中的日志被认为彼此相似,而不同组中的日志消息则不相似。

聚类完成后,利用对比学习辅助Context Encoder模块的训练。对于每个日志随机选择一个相似的日志和|Vd|个不同的日志。来自相似上下文的两个编码向量之间的距离更近。而不相似的日志距离更远。Context Similarity模块只在训练阶段充当辅助模块,在在线解析日志时将被禁用。上下文相似度模块只会在训练过程中带来额外的时间成本,而不会降低推理的速度。

损失函数

该模型的损失函数由token级分类损失和上下文级对比损失两部分组成。

token级分类损失:收集Token Encoder模块和Context Encoder模块生成的编码向量,将它们连接起来,并在其上面添加分类层进行预测。

token级分类损失可以表述为:

yi是目标token的标注,yi^是预测的token概率,N为token总数。

上下文级的损失函数:

v 代表由上下文编码模块生成的目标日志上下文的编码向量;

vs 表示相似的日志向量,vd 表示不相似的日志向量;

对于每个v,随机选择一条相似的日志消息和|Vd|个不相似的日志消息(默认|Vd| = 3)。由上下文级别的对比损失函数,UniParser被迫压缩来自相似日志的上下文编码向量,而不是来自不同日志消息的上下文编码向量。

两个损失函数的总损失函数为:,λ默认为0.01,以平衡两种损失函数的重要性。

实验

为了评估UniParser的有效性和效率,本节中,我们首先描述实验设置。然后,我们介绍了两个评估指标,包括之前组准确度,以及本文中提出的另一个指标,该指标更符合日志解析的实际目标。

实验设置

基于从LogPai基准收集的数据集进行实验,包括来自16个不同系统的各种日志,跨越分布式系统、超级计算机、操作系统、移动系统、服务器应用程序和独立软件。每个日志消息都用一个日志模板标记为ground truth。UniParser需要将日志消息拆分为token,并分别预测它们的类。因此将消息级标签转换为token级标签。由于原始版本的标签存在一些错误,我们在转换过程中也对一些标签进行了校准。

在配备NVIDIA Tesla P100 GPU和CUDA 10.2的GPU服务器上进行了实验。代码是基于PyTorch 1.4实现的。在训练过程中,使用Adam优化器,初始学习率为0.002。批大小为256,训练模型4个epoch。在线解析阶段,批大小设置为512。在Context Encoder模块中,设置k = 3。在Context Similarity模块中,我们设置|Vd| = 3。

组精度

组精度:已被广泛用于评估日志解析器,度量一组按已识别的模板(由日志解析器生成)分组的日志消息与属于同一真实日志模板的相应日志消息之间的对齐程度。组精度更倾向于将相同模板下的日志正确分组在一起,而日志模板和参数可能无法正确识别。例如,图1中的日志消息通过现有的日志解析器进行了完全正确的分组,即分组准确率为100%。但是,"/etc/data/"和"success"由于在日志中不变性而被错误地识别为模板的一部分。因此组精度不能直接反映日志解析器是否正确解析了消息。

消息精度

MLA:本文提出使用消息级精度来克服组精度的缺点,在组精度中,当且仅当消息的每个令牌都被正确标识为模板或参数时,日志消息就被认为是正确解析的。这个指标比组精度严格得多,因为任何错误的日志token识别都会导致整个日志消息的错误解析结果。例如,图4中的MLA是由于只有左组(3条日志消息)的日志被完全正确解析。

将本文模型与四种最先进的方法进行比较(包括Drain、AEL、LenMa和 LFA)。这些日志解析器涵盖了大多数类型的解析技术,并在公共数据集上实现了良好的结果。对于每个要测试的数据集,基于其他15个数据集进行跨源训练,并将训练过的模型应用到目标数据集。由于Group Accuracy度量的是ground truth模板下的日志集与解析器给出的预测模板之间的重叠,因此需要将相似的预测日志模板下的日志分组在一起进行评估。表1和表2分别显示了两个指标(组准确度、消息准确度)的结果。

除了解析精度之外,性能是日志解析器的另一个关键指标。比较UniParser与其他日志解析器在不同日志数据量下的运行时间。值得注意的是,包括了为UniParser加载数据的时间成本。结果如图5所示(X、Y轴均为对数尺度)。结果显示UniParser的运行时间随着对数规模的扩展而缓慢增加。此外,由于基于GPU加速的日志标记并行预测,我们的模型比其他传统解析器运行速度更快。即使是在100万条日志消息的规模上,UniParser也花了大约140秒,这只是AEL(214秒)所用时间的一半,Drain(482秒)所用时间的四分之一左右。

组件评估

评估主要组件和参数的有效性。Android日志数据集包含数百个日志模板和复杂的模式,在16个日志数据集中具有代表性,因此实验基于Android日志数据集进行。Group Accurac不能正确地度量日志解析器的性能,此处只使用MLA度量。

首先对模型中各组成部分的有效性进行了考察,UniParser在仅使用Token Encoder模块(0.352 MLA)时表现出较差的准确性,而在添加了Context Encoder模块(0.587 MLA)后实现了快速提升。表明Context Encoder模块从上下文学习通用模式,从而实现目标标记分类。此外,上下文相似度模块显著提高了UniParser的准确性(0.838 MLA),这证明了它在使Context Encoder模块对特征向量编码更精确方面的有用性。

参数分析,探索Context Encoder模块中k的影响,它表示目标token周围的token数量。将k的值从1调整到5,观察MLA的变化。结果表明,MLA在整个范围内(0.78 ~ 0.84)相对稳定。当k在[1,3]时,它逐渐增加,但如果k继续增加,它下降。这意味着上下文标记确实有助于捕获语义模式。相反,远离目标标记的标记可能不能提供有效的上下文信息,并可能给模型带来噪声,降低UniParser的准确性。

与序列标记模型的比较。与双向LSTM-CNNs-CR 比较,常用的序列标记模型,也可以用来对日志标记进行分类。Bi-LSTM- cnns - crf首先利用CNN将每个单词编码为向量表示,然后将单词级表示送入Bi-LSTM以获取上下文信息。最后,在Bi-LSTM的基础上,采用顺序CRF对整个句子的标签进行解码。结果表明,基于深度学习的日志解析器受益于标记级别上的监督标签,并且确实比以前的无监督方法性能更好(两个模型都优于其他现有的日志解析器,如Android数据集上的Drain);另一方面,我们的UniParser优于双向LSTM-CNNs-CRF,这证明了我们提出的模型的有效性。

模型微调:训练和目标日志源之间的模式可能不同。为了解决这个问题,设计了一个在线反馈机制来微调目标日志数据下的UniParser模型。工程师只需要检查几行解析过的结构化日志,并根据领域知识校准结果(模板或参数)。然后将这些带标签的日志输入UniParser,以使模型快速适应新的日志源。对proxyfier数据集的模型进行了微调,UniParser在这里表现最差。结果如表4所示。可以看出,在使用数十个带标签的日志进行微调后,UniParser模型可以实现解析精度的快速提高。

标签的效果。UniParser依赖于标记的日志数据,这意味着在训练时需要一些标记工作。标记的日志数据集用于离线监督学习,可以一次性标记。从实验结果可以看出我们的模型能够从异构日志源学习常见的日志模式,并且可以直接应用于大多数新的日志源,而无需额外的标记工作。即使对于具有不同模式的日志,如proxfier数据集中的那些日志,少量的微调也足够了。

Token划分,UniParser将日志解析任务转换为日志token分类问题。根据一些特殊的符号,如空格、制表符和逗号,对原始日志消息中的标记进行拆分,由于日志消息的复杂性,一些日志token很难拆分。如,在日志信息“Process A done this 1 time(s)”中,括号中的“(s)”不能与前面的标记“time”分开,也不能作为参数。在今后的工作中,我们将设计有效的机制来处理这种罕见的情况。

实际中的应用

到目前为止,UniParser已经成功应用于Microsoft 365和Azure Cloud中的多个日志分析场景,包括安全部署保护、性能问题诊断、基于日志的异常检测等。与现有的日志解析器相比,UniParser在复杂的工业日志数据上实现了更高的解析精度和更强的鲁棒性,极大地提高了各种基于日志的下游性能任务。

结论

日志解析是自动日志分析的基础,它负责将半结构化的原始日志转换为结构化的格式。本文中提出了一种基于深度学习的新模型UniParser,用于从异构日志数据中捕获常见的日志行为。UniParser利用一个Token Encoder模块和一个Context Encoder模块来捕获模板和参数的模式。上下文相似度模块是专门设计来关注学习模式的共性的。在公共日志数据集上对UniParser进行了评估,结果显示UniParser在组准确度上优于最先进的解析器12%,消息准确度提升40%

参考:

[2202.06569] UniParser: A Unified Log Parser for Heterogeneous Log Data (arxiv.org)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值