文章系列链接
背景
针对实时采集的日志数据,如何从实时的日志中监控服务的稳定性;如何及时的将服务的异常通知到相关人员;如何根据一段时间内的时序日志消除抖动,更好的提高企业运维人员的效率。。。等等这些问题,都需要建立在如何快速且尽可能准确的发现异常。
日志服务团队具备强大的日志采集功能,针对建立索引的日志进行快速的查询和分析能力。基于此,我们团队将时序数据分析功能整合到日志服务中去,结合更加强大的告警功能,帮助用户根据自己的业务需求,快速的构建报警规则,提高效率。
指标说明
实验对象
- 以SLS杭州Region的oplog为例
针对集群稳定性的关注指标
- 最近1小时内请求状态成功的平均延时
- 最近1小时内请求异常数量
异常检测实际案例分析
一个平稳态例子
最近1小时内请求状态成功的平均延迟
* and region: hangzhou |
select
date_trunc('minute', __time__ - __time__ % 60) as t,
count_if(Status=200) as succ,
count_if(Status>200) as err,
avg(Latency) as Latency
from log GROUP BY t order by t limit 10000
上图中的蓝色折线表示:每分钟平均请求成功的量;绿色折线表示:每分钟平均请求失败的量;红色的折线表示:每分钟平均请求的延迟。通过上图中的曲线可知,针对succ或这err这两个指标进行判断,却不能得到很好的判断,因此,将上述指标综合考虑一下,得到一个异常占比指标。
* and region: hangzhou |
select
time,
err*1.0 / (succ + err) as ratio
from (
select
__time__ - __time__ % 30 as time,
count_if(Status > 200) as err,
count_if(Status=200) as succ
from log GROUP BY time ) limit 2000
上图中表示每分钟$\frac{err}{succ + err}$的统计结果图,可以真实上述曲线进行时序建模,自动发现异常。具体的操作如下:
* and region: hangzhou |
select
ts_predicate_arma(time, ratio, 5, 1, 1, 1, 'avg')
from (
select
time,
err*1.0 / (succ + err) as ratio
from (
select
__time__ - __time__ % 30 as time,
count_if(Status > 200) as err,
count_if(Status=200) as succ
from log GROUP BY time order by time) ) limit 2000
上图表示使用ts_predict_arma函数,对时序ratio 曲线建立时序统计模型 arma(p=5,q=1) ,并利用SLS(日志服务)中内置的异常检测策略,得到的检测结果。其中蓝色线表示实际的 ratio 时序状态,红色曲线表示针对历史数据学习得到的有效的预测曲线,浅绿色的区域表示有效的预测置信区间,红色的空心点表示发生异常的时间点。
一个抖动较大例子
针对杭州弹内集群该统计指标的状态
* and region: hangzhou_corp |
select
time,
err*1.0 / (succ + err) as ratio
from (
select
__time__ - __time__ % 30 as time,
count_if(Status > 200) as err,
count_if(Status=200) as succ
from log GROUP BY time order by time ) limit 2000
上图中 $\frac{err}{err + succ}$ 的抖动较为异常,分析下日志,大部分是因为请求时产生了400或者401的错误(用去请求的参数不对、或者是权限异常、或是心跳部分异常)。这种折线,可以使用时序统计模型么?来来来,具体的操作如下:
* and region: hangzhou_corp |
select
ts_predicate_arma(time, ratio, 5, 1, 1, 1, 'avg')
from (
select
time,
err*1.0 / (succ + err) as ratio
from (
select
__time__ - __time__ % 30 as time,
count_if(Status > 200) as err,
count_if(Status=200) as succ
from log GROUP BY time )) limit 2000
上图中的结果是使用 ts_predict_arma 函数,使用 arma(p=5,q=1) 的参数进行学习,得到上图的曲线,其中蓝色折线表示:原始的观测序列,红色折线表示:时序模型的预测曲线,绿色区域表示可靠的致信区间。
估计有的同学会有如下问题?
- 为何红色折线与蓝色折线抖动的幅度差距有点大呢?
- 为何蓝色折线超出了绿色区域,但是却没有被标记为异常点呢?
疑问说明?️?️?️
- 预测和实际之间的差异是为何???
围观过SLS机器学习介绍(01):时序统计建模和SLS机器学习介绍(03):时序异常检测建模的同学估计就有答案了哈!!
内部在进行时序建模之前,预先对原始数据进行一个平滑操作,该操作是对调用方是透明的,具体的结果如下:
* and region: hangzhou_corp |
select
ts_smooth_fir(time, ratio, 'rectangle', 5, 1, 'avg')
from (
select
time,
err*1.0 / (succ + err) as ratio
from (
select
__time__ - __time__ % 30 as time,
count_if(Status > 200) as err,
count_if(Status=200) as succ
from log GROUP BY time order by time )) limit 2000
这时您再看下是不是就相似了很多了。
- 实际值超出了置信区间,却没有标记为异常点,却是为何???
日志服务(SLS)内部采取多种策略对异常点进行检测,尽可能的准确率、降低误报率。算法的具体原理原理说明型文章SLS机器学习介绍(03):时序异常检测建模。对此感兴趣的同学可以 钉钉:悟冥。
设置报警实例分析
时序函数有何不同之处??
标准的SQL函数,需要针对指定的字段进行查询和输出,一般格式如下:
select a, b, c from table; ===> a | b | c --------- 1 | 2 | 4 3 | 2 | 1 1 | 3 | 2 2 | 6 | 4
SLS针对时序函数提供了内置展开操作(这里需要重点感谢下 @马云雷 大神!),得到的结果如下:
select ts_predict_arma() from table; ===> unixtime | src | pred | upper | lower | prob --------------------------------------------- 1.0 | 1.0 | 1.0 | 1.2 | 0.75 | 0.0 2.0 | 1.0 | 1.0 | 1.2 | 0.75 | 0.0
说明: 针对时序函数,我们提供了一套原生接口,可以按照一定的格式返回一个元素,使用者需要针对需要自定展开操作,由于单节点放回容量有限,若用户的请求返回结果过大,超过了单节点容量限制,则不能成功返回。
使用异常检测函数进行报警
- 使用原生函数获取结果
* and not Status:200 and region: hangzhou |
select
ts_predicate_arma(time, Latency, 5, 1, 1, 1, 'avg') as key
from (
select
__time__ - __time__ % 30 as time,
count_if(Latency > 50000000) + 1 as Latency
from log GROUP BY time)
上述结果就是一个二维数组的结构,需要手动进行展开操作
- 手动展开操作
* and not Status:200 and region: hangzhou |
select
key1[1] as stamp,
key1[2] as src,
key1[3] as pred,
key1[4] as up,
key1[5] as low,
key1[6] as prob
from (
select
ts_predicate_arma(time, Latency, 5, 1, 1, 1, 'avg') as key
from (
select
__time__ - __time__ % 30 as time,
count_if(Latency > 50000000) + 1 as Latency
from log GROUP BY time)), unnest(key) as t(key1)
我们不关心预测,只关心最近2分钟的异常检测的结果
- 去掉预测的数据
- 找到最近2分钟的状态
* and not Status:200 and region: hangzhou |
select
stamp, src, pred, up, low, prob
from (
select
key1[1] as stamp,
key1[2] as src,
key1[3] as pred,
key1[4] as up,
key1[5] as low,
key1[6] as prob
from (
select
ts_predicate_arma(time, Latency, 5, 1, 1, 1, 'avg') as key
from (
select
__time__ - __time__ % 30 as time,
count_if(Latency > 50000000) + 1 as Latency
from log GROUP BY time)), unnest(key) as t(key1) )
where is_nan(src) = false order by stamp DESC limit 4
- 确定最近2分钟内的是否有异常
* and not Status:200 and region: hangzhou |
select
sum(prob) as sumProb
from (
select
stamp, prob
from (
select
key1[1] as stamp,
key1[2] as src,
key1[3] as pred,
key1[4] as up,
key1[5] as low,
key1[6] as prob
from (
select
ts_predicate_arma(time, Latency, 5, 1, 1, 1, 'avg') as key
from (
select
__time__ - __time__ % 30 as time,
count_if(Latency > 50000000) + 1 as Latency
from log GROUP BY time)), unnest(key) as t(key1) )
where is_nan(src) = false order by stamp DESC limit 4)
最终将上述查询作为一个告警的SQL,在日志服务的Web端,可以使用如下的操作。
具体的配置如下:
PS: 上述截图还是旧版本的告警设置,新的告警系统功能强大,敬请期待哈!
Tips
- 一般情情况下,我就单独针对告警设置一个仪表盘,将时序的告警规则嵌入在页面中,针对现有的报警一目了然,我的具体截图如下:
硬广时间
日志进阶
阿里云日志服务针对日志提供了完整的解决方案,以下相关功能是日志进阶的必备良药:
- 机器学习语法与函数: https://help.aliyun.com/document_detail/93024.html
- 日志上下文查询:https://help.aliyun.com/document_detail/48148.html
- 快速查询:https://help.aliyun.com/document_detail/88985.html
- 实时分析:https://help.aliyun.com/document_detail/53608.html
- 快速分析:https://help.aliyun.com/document_detail/66275.html
- 基于日志设置告警:https://help.aliyun.com/document_detail/48162.html
- 配置大盘:https://help.aliyun.com/document_detail/69313.html
更多日志进阶内容可以参考:日志服务学习路径。
联系我们
纠错或者帮助文档以及最佳实践贡献,请联系:悟冥
问题咨询请加钉钉群: