时序分析

云服务和 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 运算符创建由三个时序组成的集,其中:
  • 实际时序数据结构是每个时间箱的聚合值的数值数组。 我们将使用 render timechart 进行可视化。

上表包含三个分区。 如下图所示,我们可为每个 OS 版本创建不同的时序:Windows 10(红色)、7(蓝色)和 8.1(绿色):

Time series partition.

时序分析函数

在本部分,我们将执行典型的时序处理函数。 创建一组时序后,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

Time series filtering.

回归分析

Azure 数据资源管理器支持使用分段线性回归分析来评估时序的趋势。

  • 使用 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)

Time series regression.

  • 蓝色:原始时序
  • 绿色:拟合的线条
  • 红色:两条拟合的线条

注意

该函数准确检测到了跳接(级别变化)点。

季节性检测

许多指标遵循季节性(周期)模式。 云服务的用户流量通常包含每日和每周模式,在工作日的大约中段时间,流量是最高的;在夜间和周末,流量是最低的。 IoT 传感器按固定的间隔测量指标。 温度、压力或湿度等物理测量值也可能呈现季节性的行为。

以下示例针对 Web 服务的一个月流量(2 小时箱)应用季节性检测:

demo_series3
| render timechart 

Time series seasonality.

注意

如果特定的非重复周期不存在,则表示出现异常

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

Time series operations.

  • 蓝色:原始时序
  • 红色:经过平滑处理的时序
  • 绿色:剩余的时序

时序的大规模工作流

以下示例演示如何在几秒钟内针对数千个时序大规模运行这些函数,以进行异常情况检测。 若要查看 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) 

Time series at scale.

上述行为有误导性,因为单个正态时序是从数千个可能具有异常模式的不同实例聚合而成的。 因此,我们需为每个实例创建一个时序。 实例由 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)')

Time series top two.

显示实例:

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 个时序,并检测到了读取计数骤然下降的两个异常时序。

将这些高级功能与高速性能相结合,可为时序分析提供独特且强大的解决方案。