传统日志异常检测方法
说到日志异常检测,很多人第一反应就是上深度学习。但别急,在实际生产环境里,传统方法依然占据着相当大的比重。我个人习惯在引入复杂模型之前,先用传统方法跑一遍基线。为什么?因为简单、快、容易解释。我刚开始接触这个领域时,觉得深度学习才是正道,结果被同事一句“你这条规则三行代码就能搞定,为什么要训练一天?”给问住了。从那以后,我就老老实实把传统方法摸透了。
基于规则的方法
这应该是大家最先想到的。说白了,就是提前定义好“什么样算异常”。具体来说,主要有两类规则写出方式:
- 正则表达式匹配: 直接写模式串。比如看到 “ERROR: OutOfMemoryError” 就知道出事了。
- 关键字黑名单: 把 “failed”、“exception”、“timeout” 这类词列出来,命中就报警。
举个简单的例子,我在处理 Java 应用日志时,经常要抓 StackOverflowError。规则大概是这样:
import re
def rule_based_detect(log_line):
patterns = [
r"OutOfMemoryError",
r"StackOverflowError",
r"NullPointerException"
]
for p in patterns:
if re.search(p, log_line):
return True
return False
嗯,这里要注意。规则太死板容易漏报,但太宽泛又全是误报。我曾在某金融项目里见过一套写了上千条规则的系统,维护成本高得吓人。每次改一条规则,就要全量回归测试,痛苦得很。
基于统计的方法
与其死记硬背异常长什么样,不如看看日志的统计特征。正常行为和异常行为,在统计分布上应该有区别吧?
举个例子,假设某个接口在正常情况下,每秒返回10条日志。突然某天变成了1000条,这肯定有问题。常见的统计方法有:
| 方法 | 原理 | 适用场景 |
|---|---|---|
| 泊松分布建模 | 假设事件发生次数服从泊松分布,小概率事件算异常 | 计数型指标,如请求数、错误数 |
| Z-score / 3-sigma | 计算偏离均值的标准差数,超过3视为异常 | 数值型指标,响应时间、CPU使用率 |
| MPU 方法 | 基于滑动窗口的移动平均与标准差 | 平滑趋势,减少噪声干扰 |
我做运维那会,最常用的就是 3-sigma 法。举个例子:
import numpy as np
def zscore_detect(values, threshold=3):
mean = np.mean(values)
std = np.std(values)
return [(v, abs(v - mean) / std)
for v in values
if abs(v - mean) / std > threshold]
看着挺简单,对不?但坑也多。我曾经遇到过数据本身就不符合正态分布的情况,直接用 3-sigma 检出率特别差。后来学乖了,先做分布检验,不行就用百分位数法。
基于时间序列的方法
日志本质上是时间序列数据。一条日志在“什么时候产生”,这个时间戳本身就包含大量信息。很多异常,尤其是慢变故障,在规则和统计里都看不出来,但时间序列模型能发现趋势变化。
常见思路有两种:
- 移动平均法: 用最近一段时间的历史值预测下一时刻的值。预测值和真实值差异过大,就算异常。
- ARIMA 模型: 更经典的时序建模方式,考虑自相关性和滑动平均。适合有明显周期性的日志流量。
给你看个简单的滑动平均判断异常的例子:
def moving_average_detect(series, window=5, factor=2):
ma = np.convolve(series, np.ones(window)/window, mode='valid')
residual = series[window-1:] - ma
threshold = factor * np.std(residual)
anomalies = np.where(np.abs(residual) > threshold)[0] + window - 1
return anomalies.tolist()
不过要注意,时间序列方法对季节性要求比较高。我遇到过好几次,高峰期流量本身就在涨,模型却把它当异常报出来了。嗯,这里的关键是——你得先分解出趋势和周期,再做残差检测。
以上就是传统方法的核心内容。整个流程下来你会发现,这些方法虽然各有短板,但胜在简单、可解释。在实际项目中,我通常会先用规则方法过滤掉明显的异常,然后对剩余日志做统计分析,最后再用时间序列盯住连续趋势。嗯,这一套组合拳打下来,大多数常规问题都能搞定。至于那些隐藏在数千条日志里的、非线性模式的异常,就得把舞台交给深度学习来登场了。