时序分析
云服务和 IoT 设备生成可用于获取见解的遥测数据,例如监视服务运行状况、物理生产流程和使用趋势。 执行时序分析是识别这些指标模式与典型基线模式相比的偏差的一种方法。
Kusto 查询语言 (KQL) 原生支持创建、操作和分析多个时序。 本文介绍如何使用 KQL 在几秒钟内创建和分析数千个时序,实现近实时的监视解决方案和工作流。
时序的创建
在本部分,我们将使用 make-series
运算符方便直观地创建大量正则时序,并根据需要填充缺失值。
时序分析的第一个步骤是将原始遥测表分区并转换为一组时序。 该表通常包含时间戳列、上下文维度和可选指标。 维度用于将数据分区。 目标是按固定的时间间隔为每个分区创建数千个时序。
输入表 demo_make_series1 包含任意 Web 服务流量的 60 万条记录。 使用以下命令对 10 条记录进行采样:
demo_make_series1 | take 10
生成的表包含一个时间戳列、三个上下文维度列,但不包含指标:
时间戳 | BrowserVer | OsVer | 国家/地区 |
---|---|---|---|
2016-08-25 09:12:35.4020000 | Chrome 51.0 | Windows 7 | 英国 |
2016-08-25 09:12:41.1120000 | Chrome 52.0 | Windows 10 | |
2016-08-25 09:12:46.2300000 | Chrome 52.0 | Windows 7 | 英国 |
2016-08-25 09:12:46.5100000 | Chrome 52.0 | Windows 10 | 英国 |
2016-08-25 09:12:46.5570000 | Chrome 52.0 | Windows 10 | 立陶宛共和国 |
2016-08-25 09:12:47.0470000 | Chrome 52.0 | Windows 8.1 | 印度 |
2016-08-25 09:12:51.3600000 | Chrome 52.0 | Windows 10 | 英国 |
2016-08-25 09:12:51.6930000 | Chrome 52.0 | Windows 7 | 荷兰 |
2016-08-25 09:12:56.4240000 | Chrome 52.0 | Windows 10 | 英国 |
2016-08-25 09:13:08.7230000 | Chrome 52.0 | Windows 10 | 印度 |
由于没有指标,我们只能生成一组时序,用于表示由 OS 使用以下查询分区的流量计数本身:
let min_t = toscalar(demo_make_series1 | summarize min(TimeStamp));
let max_t = toscalar(demo_make_series1 | summarize max(TimeStamp));
demo_make_series1
| make-series num=count() default=0 on TimeStamp from min_t to max_t step 1h by OsVer
| render timechart
- 使用
make-series
运算符创建由三个时序组成的集,其中:num=count()
:流量的时序from min_t to max_t step 1h
:时序是在时间范围(表记录的最旧和最新时间戳)的 1 小时箱中创建的default=0
:指定缺失箱的填充方法,以创建正则时序。 或者使用series_fill_const()
、series_fill_forward()
、series_fill_backward()
和series_fill_linear()
进行更改by OsVer
:由 OS 分区
- 实际时序数据结构是每个时间箱的聚合值的数值数组。 我们将使用
render timechart
进行可视化。
上表包含三个分区。 如下图所示,我们可为每个 OS 版本创建不同的时序:Windows 10(红色)、7(蓝色)和 8.1(绿色):
时序分析函数
在本部分,我们将执行典型的时序处理函数。 创建一组时序后,KQL 支持使用一系列函数(数量不断扩充)来处理和分析这些时序。 下面将介绍几个用于处理和分析时序的有代表性的函数。
筛选
在信号处理中,筛选是常见的活动,可用于完成时序处理任务(例如,平滑化干扰信号、变化检测)。
- 有两个泛型筛选函数:
series_fir()
:应用 FIR 筛选器。 用于方便计算变化检测中时序的移动平均值和差异。series_iir()
:应用 IIR 筛选器。 用于指数平滑与累计求和。
- 通过将大小为 5 个箱的新移动平均时序(名为 ma_num)添加到查询,来
Extend
(扩展)时序集:
let min_t = toscalar(demo_make_series1 | summarize min(TimeStamp));
let max_t = toscalar(demo_make_series1 | summarize max(TimeStamp));
demo_make_series1
| make-series num=count() default=0 on TimeStamp from min_t to max_t step 1h by OsVer
| extend ma_num=series_fir(num, repeat(1, 5), true, true)
| render timechart
回归分析
分段线性回归分析可用于评估时序的趋势。
- 使用 series_fit_line() 将最佳线条拟合到时序即可实现一般趋势检测。
- 使用 series_fit_2lines() 可以检测相对于基线的趋势变化,这种变化在监视方案中非常有用。
时序查询中 series_fit_line()
和 series_fit_2lines()
函数的示例:
demo_series2
| extend series_fit_2lines(y), series_fit_line(y)
| render linechart with(xcolumn=x)
- 蓝色:原始时序
- 绿色:拟合的线条
- 红色:两条拟合的线条
注意
该函数准确检测到了跳接(级别变化)点。
季节性检测
许多指标遵循季节性(周期)模式。 云服务的用户流量通常包含每日和每周模式,在工作日的大约中段时间,流量是最高的;在夜间和周末,流量是最低的。 IoT 传感器按固定的间隔测量指标。 温度、压力或湿度等物理测量值也可能呈现季节性的行为。
以下示例针对 Web 服务的一个月流量(2 小时箱)应用季节性检测:
demo_series3
| render timechart
- 使用 series_periods_detect() 自动检测时序中的周期。
- 如果知道某个指标应有特定的非重复周期,并且想要验证这些周期是否存在,则使用 series_periods_validate()。
注意
如果特定的非重复周期不存在,则表示出现异常
demo_series3
| project (periods, scores) = series_periods_detect(num, 0., 14d/2h, 2) //to detect the periods in the time series
| mv-expand periods, scores
| extend days=2h*todouble(periods)/1d
periods | 评分 | days |
---|---|---|
84 | 0.820622786055595 | 7 |
12 | 0.764601405803502 | 1 |
该函数会检测每日和每周季节性。 每日评分小于每周评分,因为周末的天数不同于工作日天数。
元素对应的函数
可针对时序执行算术和逻辑运算。 使用 series_subtract() 可以计算残差时序(原始指标与平滑化指标之差),并查看剩留信号中的异常:
let min_t = toscalar(demo_make_series1 | summarize min(TimeStamp));
let max_t = toscalar(demo_make_series1 | summarize max(TimeStamp));
demo_make_series1
| make-series num=count() default=0 on TimeStamp in from min_t to max_t step 1h by OsVer
| extend ma_num=series_fir(num, repeat(1, 5), true, true)
| extend residual_num=series_subtract(num, ma_num) //to calculate residual time series
| where OsVer == "Windows 10" // filter on Win 10 to visualize a cleaner chart
| render timechart
- 蓝色:原始时序
- 红色:经过平滑处理的时序
- 绿色:剩余的时序
时序的大规模工作流
以下示例演示如何在几秒钟内针对数千个时序大规模运行这些函数,以进行异常情况检测。 若要查看 DB 服务的读取计数指标在过去四天的几个示例遥测记录,请运行以下查询:
demo_many_series1
| take 4
TIMESTAMP | Loc | Op | DB | DataRead |
---|---|---|---|---|
2016-09-11 21:00:00.0000000 | Loc 9 | 5117853934049630089 | 262 | 0 |
2016-09-11 21:00:00.0000000 | Loc 9 | 5117853934049630089 | 241 | 0 |
2016-09-11 21:00:00.0000000 | Loc 9 | -865998331941149874 | 262 | 279862 |
2016-09-11 21:00:00.0000000 | Loc 9 | 371921734563783410 | 255 | 0 |
和简单的统计信息:
demo_many_series1
| summarize num=count(), min_t=min(TIMESTAMP), max_t=max(TIMESTAMP)
num | min_t | max_t |
---|---|---|
2177472 | 2016-09-08 00:00:00.0000000 | 2016-09-11 23:00:00.0000000 |
在读取指标的 1 小时箱中生成时序(总共 4 天 * 24 小时 = 96 个点)会产生正态模式波动:
let min_t = toscalar(demo_many_series1 | summarize min(TIMESTAMP));
let max_t = toscalar(demo_many_series1 | summarize max(TIMESTAMP));
demo_many_series1
| make-series reads=avg(DataRead) on TIMESTAMP from min_t to max_t step 1h
| render timechart with(ymin=0)
上述行为有误导性,因为单个正态时序是从数千个可能具有异常模式的不同实例聚合而成的。 因此,我们需为每个实例创建一个时序。 实例由 Loc(位置)、Op(运算)和 DB(特定计算机)定义。
可以创建多少个时序?
demo_many_series1
| summarize by Loc, Op, DB
| count
计数 |
---|
18339 |
现在,我们将创建由读取计数指标的 18339 个时序组成的集。 将 by
子句添加到 make-series 语句,应用线性回归,并选择具有最明显递减趋势的前两个时序:
let min_t = toscalar(demo_many_series1 | summarize min(TIMESTAMP));
let max_t = toscalar(demo_many_series1 | summarize max(TIMESTAMP));
demo_many_series1
| make-series reads=avg(DataRead) on TIMESTAMP from min_t to max_t step 1h by Loc, Op, DB
| extend (rsquare, slope) = series_fit_line(reads)
| top 2 by slope asc
| render timechart with(title='Service Traffic Outage for 2 instances (out of 18339)')
显示实例:
let min_t = toscalar(demo_many_series1 | summarize min(TIMESTAMP));
let max_t = toscalar(demo_many_series1 | summarize max(TIMESTAMP));
demo_many_series1
| make-series reads=avg(DataRead) on TIMESTAMP from min_t to max_t step 1h by Loc, Op, DB
| extend (rsquare, slope) = series_fit_line(reads)
| top 2 by slope asc
| project Loc, Op, DB, slope
Loc | Op | DB | slope |
---|---|---|---|
Loc 15 | 37 | 1151 | -102743.910227889 |
Loc 13 | 37 | 1249 | -86303.2334644601 |
在不到两分钟的时间内,分析了接近 20,000 个时序,并检测到了读取计数骤然下降的两个异常时序。
将这些高级功能与高速性能相结合,可为时序分析提供独特且强大的解决方案。