计算机的系统日志提供了对正在运行的系统状态的描述。日志的内容和格式在不同的系统之间,甚至在系统中的不同组件之间都可能有着很大的不同。硬件的驱动程序可能生成指示与硬件通信有问题的消息,而 Web 服务器可能记录请求了哪些页面以及何时请求其他服务。
由于日志的内容不同,用途也有着相应的不同。有关硬件的日志可用于故障排除,而 web 服务器日志用于研究流量模式以最大化业务收入。事实上,单个日志可以用于多种用途: 关于沿着不同网络路径(称为流量)的信息可能有助于用户优化网络性能或检测恶意入侵; 或者通话记录可以监控谁和何时拨打了电话,并通过进一步分析可以揭示整个城市的通话量和掉话率。
日志分析是一个丰富的研究领域,但仍然面临着诸多的挑战。那为什么日志分析既重要又困难呢?
许多日志旨在促进调试。“最有效的调试工具仍然是仔细的思考,再加上明智的 print 语句。”尽管今天的程序比30年前的程序复杂了4个数量级,许多人仍然使用 printf 来记录控制台或本地磁盘的日志,并使用一些手动检查和正则表达式的组合来定位特定的消息或模式。
调试日志最简单也是最常见的用途是对特定消息使用 grep。如果认为程序因为网络故障而崩溃,那么可能会尝试在服务器日志中找到“连接丢失”消息。在许多情况下,很难确定要搜索什么,因为日志消息和观察到的症状之间没有定义良好的映射。当 Web 服务突然变慢时,不太可能看到一个明显的错误消息说,“ ERROR: 服务延迟增加了10% ,因为第 x 行的 bug 被触发了。”相反,用户通常会搜索严重性关键字,比如“ error”或“ failure”。然而,这样的严重级别经常没有被准确地使用,因为开发人员很少完全了解最终将如何使用这些代码。
当开发人员编写日志消息的 print 语句时,它被绑定到程序源代码的上下文。然而,信息的内容通常排除了这个上下文。如果不了解 print 语句周围的代码,或者不知道是什么导致程序进入了执行路径,消息的一些语义可能会丢失,也就是说,在没有上下文的情况下,日志消息可能难以理解。
另一个挑战是,日志文件通常被设计为表示单个事件流。然而,来自多个源的消息可能在运行时(来自多线程或多进程)和静态模块交错。对于运行时的交织,线程 ID 不能解决问题,因为可以为独立任务重用线程。一直以来,人们努力自动包含消息上下文(例如,X-Trace) ,或者从消息内容中进行推断,但是这些都不能完全捕获开发人员的意图和期望。
静态交织场景更具挑战性,因为不同的模块可能由不同的开发人员编写。因此,单个日志消息可能有多种解释。例如,“连接丢失”可能对网络库的作者非常重要,但对于通过底层抽象避免错误的应用程序作者来说就不那么重要了。共享库的作者通常不可能预测哪些消息对用户有用。
日志记录通常意味着一些内部同步。这可能会通过改变线程交织模式和模糊问题而使多线程系统的调试复杂化。一个程序只在某些执行点上表现出不确定性,比如时钟中断和 i/o 通过记录所有不确定的执行点,一般要重新运行整个程序来进行观察,可以在重新运行之前修改一些代码来观察程序中的任何东西。然而,对于并发程序或那些确定性执行依赖于大量数据的程序,这种方法可能是不切实际的。
在大型系统中,日志量可能过大。例如,为了调试锁竞争而对锁对象上的每个获取和释放操作进行日志记录可能会代价过高。在多模块系统中,更加困难,因为日志也是异构的,因此更不适合进行直接分析。收集、存储、排序或索引大量日志消息存在着固有的成本,其中许多消息可能永远不会被使用。调试日志的投资回报来自其诊断能力,这是很难衡量的。
有些用户需要的是聚合或统计信息,而不是单独的消息。在这种情况下,他们只能记录聚合数据或聚合数据的近似值,仍然可以得到所需统计数据的良好估计,近似提供了对于诸如 PCA 和 SVM这样的机器学习分析。这些技术在网络化或大规模分布式系统中非常关键,在这些系统中,即使从每个组件收集一个数字也会带来沉重的性能成本。这说明了裁剪工具对于特定分析的潜在好处。
机器学习技术,尤其是异常检测,通常用于发现有趣的日志消息。机器学习工具通常要求输入数据作为数字特征向量,但是将自由的文本日志消息转换为有意义的特征并非易事。一般会分析源代码,然后从文本日志中自动提取半结构化的数据,并将异常检测应用于从日志中提取的特征。
统计异常检测仍然面临挑战。即使某些信息在统计意义上是不正常的,也可能没有进一步的证据表明这些信息是原因、症状,或者仅仅是无害的。此外,统计方法在很大程度上依赖于日志质量,特别是是否记录了“重要”事件,而这些方法本身并没有定义什么是“重要的”。
静态程序分析可以通过分析程序中可能导致消息产生的路径来帮助发现特定消息的根本原因。静态分析还可以通过寻找分歧点来揭示提高日志质量的方法,程序执行可能从这些分歧点进入错误路径; 这些分歧点是日志分析的最佳选择。目标系统的启发式和领域知识通常使这种分析更有效。
日志分析可以帮助优化或调试系统性能。理解系统的性能通常与理解如何使用系统中的资源有关。
有些日志与调试的情况相同,例如记录并锁定操作以调试瓶颈。有些日志跟踪单个资源的使用情况,会产生一个时间序列。资源使用统计数据通常以每个时间段累积使用的形式出现(例如,在最后一分钟传输的n个字节),使用带宽数据描述网络或磁盘性能,页交换描述内存有效性,或者 CPU 利用率描述负载平衡质量。
与调试用例一样,必须在上下文中解释性能日志。其中,有两种上下文在性能分析中特别有用: 出现性能数字的环境和系统的工作负载。
性能问题通常由组件之间的交互引起,为了揭示这些交互,可能必须综合来自多个源生成的异构日志的信息。合成可能是一个挑战。除了异构的日志格式之外,分布式系统中的组件可能在确切的时间上存在分歧,使得跨多个组件事件的精确排序无法重构。另外,对一个组件无害的事件(例如,将日志刷新到磁盘)可能会对另一个组件造成严重问题(例如,I/O的资源竞争)。由于引起问题的组件不太可能记录事件,因此可能很难捕获这个根本原因。这只是所出现困难中的一小部分。
解决这个问题的一个方法是计算影响力,通过寻找令人惊讶的、在时间上相关的行为来推断组件或组件之间的关系。即使这些日志是稀疏的、不完整的、没有已知的语义,即使交互机制是未知的,也需要量化产生异构日志的组件之间的交互。
在消息或请求被系统处理时,对其进行跟踪的方法能够说明事件的顺序和工作负载的影响。例如,一种类型的请求可以很容易地通过缓存数据进行服务,而另一种类型的请求则不能。这种跟踪方法通常需要能够提供支持的检测工具,但是除了了解性能之外,它对正确性调试也很有用。
这方面的一个突出挑战是测量行为对影响测量本身的风险。耗费资源的大量日志记录可能会使首先这些资源的任务复杂化。我们测量的越多,我们就越不能准确地理解系统的性能特征。即使是保守的跟踪机制在实践中也通常会引入不可接受的开销。
减少日志记录对性能影响的一种方法是抽样。危险在于,抽样调查可能会错过罕见的事件。但是,如果有数百万乃至数亿个采样实例在运行,那么在可以在捕获罕见事件的同时保持较低的采样率。
采样技术的有效实现需要能够打开和关闭单个日志站点,而不需要重新启动执行。像 DTrace 这样的旧系统仍然需要静态检测的日志站点,但是,日志的后处理是一个收集、处理和分析软件执行跟踪的平台,它允许用户指定他们想要测量的事件,用声明性语言表述为查询; 然后平台在运行的系统中插入动态的plug-in,聚合测量数据,并提供分析机制,所有这些都是针对这些查询的。当应用于分布式系统中的基准代码时,这样的系统显示了个位数的开销百分比。结合基于抽样的日志记录的动态日志记录可能是解决需要大规模详细日志记录问题的关键方案。
日志还用于应用的安全性分析,如检测违规或不当行为,以及执行安全事件的事后检查。根据系统和威胁模型,几乎任何类型的日志都可以进行安全分析,例如防火墙、登录会话、资源利用率、系统调用、网络流等相关的日志。
入侵检测通常需要根据日志重建会话。考虑一个与入侵检测相关的例子,即检测对系统的未经授权的访问。当用户通过 SSH 远程登录到计算机时,计算机将生成与登录事件相对应的一条日志。在 Mac OS x 上,这些消息显示一个名为 XX的用户从特定的 IP 地址和端口号交互地访问了机器。
常识告诉我们,注销消息应该与之前的登录消息相匹配,但是,有些日志行没有任何语法可以先验地揭示它们以某种方式与登录时生成的代码行相关联,更不用说彼此之间了。换句话说,每个消息都是多个语义事件的证据,包括以下内容: 特定代码行的执行、 SSH 会话的创建或销毁,以及作为一个整体的 SSH 会话。
对安全性感兴趣的日志分析可能会问一个看似简单的问题: 这个 SSH 会话是否构成安全性破坏?
答案可能取决于一些因素,其中包括: 是否有异常大量的登录尝试失败最近?用户XX的 IP 地址熟悉吗?XX 在会话处于活动状态时是否执行了任何可疑的操作?用户名为 XX的用户是否正在休假,因此不应该登录?
需要注意的是,只有其中一些问题可以使用日志中的数据来回答。例如,可以查找在这个会话之前的大量失败的登录尝试,但是不能推断XX的真实身份,更不用说他或她的假期计划了。因此,分析的能力受到日志中信息的限制。
安全性的日志分析可以是基于签名的,用户尝试检测已知的恶意行为; 或者是基于异常事件,寻找偏离典型或良好行为并将其标记为可疑行为。签名的方法可以可靠地检测到与已知签名匹配的攻击,但对不匹配的攻击不敏感。另一方面,异常方法面临着设置一个阈值来调用可疑异常的困难: 过低,错误警报使工具无用; 过高,攻击可能未被发现。
应用的安全性还面临着与敌人斗智斗勇。为了避开日志分析工具的注意,攻击者将试图使攻击期间生成的日志看起来与正确操作期间生成的日志完全或接近相同。对于不完整的日志,分析无能为力。开发人员可以尝试提高日志记录覆盖率,这使得对手更难避免留下活动的证据,但这并不一定使区分“健康”日志和“可疑”日志变得更容易。
日志数据可以用来预测。预测模型有助于实现资源供应、容量规划、工作负载管理、调度和配置优化的自动化或提供数据方面的洞察力。从商业角度来看,预测模型可以指导营销策略、广告投放或库存管理。
针对具体的系统,建立并完善了一些分析模型。专家手动识别依赖关系和相关度量标准,量化组件之间的关系,并设计预测策略。这些模型通常用于构建模拟器,模拟器重播预期的工作负载扰动或负载量,以提出假设问题。在I/O子系统、磁盘阵列、数据库和静态 Web 服务器上都有使用分析模型进行性能预测的示例。然而,这种方法有一个重大的实际缺点,即实际系统变化频繁,分析技术必须要跟上这些变化。
尽管建模技术可能在不同的系统中是通用的,但是为构建模型而挖掘的日志数据以及预测的度量可能会有所不同。例如,I/O 子系统和包含时间戳、事件类型、 CPU 配置文件以及其他每个操作系统的事件来预测 I/O 子系统的性能,也可以利用捕获 I/O 请求速率、请求大小、运行计数、队列长度和其他属性的跟踪来构建分析模型,以预测磁盘阵列吞吐量。
许多分析模型都是单层的: 每个预测指标都有一个模型。在其他场景中,需要一个模型层次结构来根据其他性能指标来预测单个性能指标。例如,使用包含时间戳、请求类型(GET vs. POST)、请求的字节、 URI 和其他字段的 Web 服务器跟踪来预测存储响应时间、存储 I/O 和服务器内存。预测不同负载条件下服务器响应时间的模型可以由存储量和服务器内存模型组成。另一个例子是,日志跟踪记录访问、块访问、物理磁盘传输、吞吐量和平均响应时间可用于建立多级排队的网络模型,以预测物理和逻辑设计决策对数据库性能的影响。
分析模型的一个缺点是需要特定于系统的领域知识。这样的模型不能无缝地移植到新版本的系统,更不用说移植到其他系统了。随着系统变得越来越复杂,人们开始转向使用历史数据的统计模型来预测未来的工作量和性能。
回归分析是用于预测的最简单的统计建模技术。它已经应用于性能计数器,用于度量执行时间和内存子系统的影响。例如,应用于这些日志的线性回归被用来预测并行处理器上库的数据分区布局的执行时间。而应用逻辑回归模型被用来预测一组好的编译器标志。CART 使用磁盘请求的跟踪,指定到达时间、逻辑块号、请求的块和读/写类型,以预测存储系统中请求和工作负载的响应时间。
简单回归和 CART 模型都可以预测每个模型的单一指标。然而,性能指标通常具有相互依赖性,必须对每个指标进行预测,才能做出明智的调度或配置决策。为了同时预测多个指标,有一种方法是采用典型的相关分析来建立一个模型,该模型捕捉系统输入和性能特征之间的相互依赖关系,并利用该模型来预测系统在任意输入下的性能。、
虽然这些技术显示了统计学习技术在性能预测方面的威力,但是它们的使用也带来了一些挑战。
从事件日志中提取特征向量是影响预测模型有效性的关键步骤。事件日志通常包含非数字数据(例如,分类数据) ,但统计技术期望数字输入带有在数据上定义的分布概念。将事件中的非数值信息转换为有意义的数值数据可能非常繁琐,需要了解事件代表什么的领域知识。因此,即使给出一个预测,也很难确定正确的行动方向。
预测模型通常提供一个值的范围,而不是一个单一的数字; 这个范围有时代表一个置信区间,这意味着真正的价值很可能在这个区间内。是否对预测采取行动是一个必须权衡置信度与成本的决定,也就是说,对低置信度预测采取行动未必比什么都不做要好。执行可能取决于日志粒度是否与决策粒度匹配,例如,每个查询的资源利用率的日志无助于任务级别的调度决策,因为对并行性和较低级别的资源利用指标了解的并不足够。
日志分析的另一个用途是分析资源利用率、工作负载或用户行为。记录集群工作负载中任务特征的日志可用于分析大型数据中心的资源利用情况。可以利用相同的数据来了解工作负载中作业之间的相互到达时间,以及日变化模式。
除了系统管理之外,还可以还用于业务分析。例如,Web 服务器日志描述了 站点访问者的特征,它可以产生客户统计信息。Web 日志分析技术的范围从捕获页面流行趋势的简单统计演化成了描述跨多个用户会话访问模式的复杂时间序列方法。这些数据为营销活动、内容托管和资源供应提供了信息。
使用各种统计技术来分析和报告日志数据。聚类算法,如 k 均值和层次聚类组得到相似事件。马尔可夫链被用于模式挖掘,其中时间序列是必不可少的。
许多剖析和警报技术需要专家知识形式的提示。例如,K均值聚类算法要求用户指定集群的数量(k)或者提供作为种子集群中心的示例事件。其他技术需要合并或分区聚类的启发式算法。大多数技术依赖于事件的数学表示,并且分析结果以类似的术语表示。然后,可能有必要将这些数学表示映射进行还原,如果不理解日志语义,这可能会很困难。
对日志事件进行分类通常也具有挑战性。例如,要对系统性能进行分类,可以分析 CPU 利用率和内存消耗情况。假设有一个高 CPU 利用率和低内存消耗的性能配置文件,以及一个具有低 CPU 利用率和高内存消耗的单独配置文件; 当出现一个包含低 CPU 利用率和低内存消耗的事件时,不清楚它应该属于两个配置文件中的哪一个(或两者)。如果有足够多的此类事件,最好的选择可能是包含第三个配置文件。对于如何处理跨多个摘要的事件或者如何预先创建这样的摘要,并没有普遍适用的规则。
尽管摘要可以有效地对类似事件进行分组,并提供系统行为的高级视图,但它并不能直接转化为可操作的洞察力。解释摘要并使用它来做业务决策、修改系统、甚至修改分析的任务通常落在人的身上。
日志的基础设施对于支持各种应用程序至关重要。它至少需要两个特性: 日志生成和日志存储。
大多数通用日志都是非结构化文本。开发人员使用 printf 和字符串连接来生成消息,这些原语已经被很好地理解并且无处不在。然而,这种日志记录方式也有缺点。首先,将变量序列化为文本的代价高昂。其次,分析需要解析文本消息,这也可能是复杂而昂贵的。
在存储方面,基础设施聚合来自各种网络源的消息。Splunk 为来自 syslog 和其他源的非结构化文本日志编制索引,并对数据执行实时和历史分析。使用 Hadoop 存储数据,以利用分布式计算的基础设施。
选择正确的日志存储解决方案需要权衡以下因素:
对于日志保留,不存在一个放之四海而皆准的策略。这使得选择和配置日志解决方案成为一个挑战。对商业智能有用的日志通常被认为比调试日志更重要,因此保存的时间更长。相比之下,大多数调试日志尽可能长时间地存储,但是没有保存的保证,这意味着它们可能在资源压力下被删除。
日志存储解决方案在与警报和报表功能结合时更有用。这样的基础架构可以用于调试、安全性和其他系统管理任务。各种日志存储解决方案促进了告警和报表功能,但是它们留下了许多与告警节流、报表加速和预测能力有关的开放挑战。
现在的系统管理在很大程度上已经变得以日志为中心。无论是用于调试问题还是用于提供资源,日志都包含了大量可以精确定位或至少暗示解决方案的信息。
虽然日志分析技术已经取得了很大进展,但仍然存在一些较大的挑战。首先,随着系统越来越多地由许分布式组件构成,使用单个日志文件来监视来自系统不同部分的事件是很困难的。在某些情况下,来自完全不同系统的日志必须交叉关联才能进行分析。交织异构日志很少是直接的,特别是当时间戳没有在所有日志中同步或出现,而且组件之间语义不一致的时候。
其次,日志记录过程本身需要额外的管理。控制日志的冗长性对于管理开销和促进分析非常重要,尤其是在出现峰值或潜在攻击行为的情况下。日志记录机制也不应该成为传播恶意活动的通道。在最大化信息内容的同时最小化检测开销仍然是一个挑战。
第三个挑战是,尽管各种分析和统计建模技术可以挖掘大量的日志数据,但它们并不总能提供可操作的洞察力。例如,统计技术可以揭示工作负载中的异常或者系统的 CPU 利用率过高,但是不能解释如何处理它。信息的解读具有主观性,信息是否具有可操作性取决于多种因素。这是重要的调查技术,是效率,准确性和可行性的权衡。
由于在可预见的未来,人仍然是解释和处理日志过程的一部分,因此可视化技术的是值得投入的。
程序分析方法,无论是静态的还是动态的,都有望提高我们自动描述导致特定日志消息序列的交互能力,使日志要么更易于进行各种分析,要么提供更全面的信息。对于如何生成更有用的日志的洞察力通常伴随着对于如何分析现有日志的洞察力,验证日志消息有效性的机制将提高日志质量,使日志分析更加有效。
随着许多企业越来越依赖于他们的计算机基础设施,这种关系的重要性也随之增加。已经看到越来越多的工具试图推断系统是如何影响用户的: 延迟如何影响购买决策; 点击模式如何描述用户满意度; 以及资源调度决策如何改变对这些资源的需求。另外,用户活动可能对系统调试有用。进一步探索用户行为(工作负载)和系统行为之间的关系,可能有助于理解要使用什么日志,何时使用以及用于什么目的。
更好的日志标准和最佳实践,将有助于提高日志分析的水平。