:orphan:

streamstats

streamstats 命令用于在按顺序处理事件时计算累积或滚动统计信息。与一次性对整个数据集进行操作的 statseventstats 不同,streamstats 以增量方式处理事件,使其适用于时间序列和基于序列的分析。

主要特性包括支持 window(滑动窗口计算)和 current(是否在计算中包含当前事件)参数,以及专门用例,例如识别趋势或检测事件序列中的变化。

比较 stats、eventstats 和 streamstats

statseventstatsstreamstats 命令都可以生成如平均值、总和和最大值等聚合。然而,它们在操作方式和产生的结果上有所不同。下表总结了这些差异。

方面 stats eventstats streamstats
转换行为 将所有事件转换为聚合结果表,丢失原始事件结构 将聚合结果作为新字段添加到原始事件中,不删除事件结构 将累积(运行)聚合结果添加到流经管道的每个事件中
输出格式 输出仅包含聚合值。原始事件不被保留 原始事件保留,额外字段包含汇总统计信息 原始事件保留,额外字段包含运行总计或累积统计信息
聚合范围 基于搜索中的所有事件(或由 by 子句定义的组) 基于所有相关事件,然后将结果添加回组中的每个事件 计算随着每个事件的处理逐步进行;可以按窗口限定范围
使用场景 当仅需要聚合结果时(例如计数、平均值、总和) 当需要聚合统计信息以及原始事件数据时 当需要跨事件流的运行总计或累积统计信息时

语法

streamstats 命令的语法如下:

streamstats [bucket_nullable=bool] [current=<bool>] [window=<int>] [global=<bool>] [reset_before="("<eval-expression>")"] [reset_after="("<eval-expression>")"] <function>... [by-clause]

以下是 streamstats 命令语法的示例:

source = table | streamstats avg(a)
source = table | streamstats current = false avg(a)
source = table | streamstats window = 5 sum(b)
source = table | streamstats current = false window = 2 max(a)
source = table | where a < 50 | streamstats count(c)
source = table | streamstats min(c), max(c) by b
source = table | streamstats count(c) as count_by by b | where count_by > 1000
source = table | streamstats dc(field) as distinct_count
source = table | streamstats distinct_count(category) by region
source = table | streamstats current=false window=2 global=false avg(a) by b
source = table | streamstats window=2 reset_before=a>31 avg(b)
source = table | streamstats current=false reset_after=a>31 avg(b) by c

参数

streamstats 命令支持以下参数。

参数 必需/可选 描述
<function> 必需 聚合函数或窗口函数。
bucket_nullable 可选 控制是否在分组聚合中将空值桶视为有效组。当为 false 时,在聚合期间不将空分组值视为一个独立的组。默认值为 plugins.ppl.syntax.legacy.preferred 的值。
current 可选 是否在汇总计算中包含当前事件。当为 true 时,包含当前事件;当为 false 时,使用前一个事件的字段值。默认值为 true
window 可选 计算统计信息时要使用的事件数量。默认值为 0(使用所有先前和当前事件)。
global 可选 仅在指定 window 时使用。决定是使用单个窗口 (true) 还是对 by 子句定义的每个组使用单独的窗口 (false)。当为 falsewindow 非零时,对 by 子句中指定字段的每个值组使用一个单独的窗口。默认值为 true
reset_before 可选 eval-expression 求值为 true 时,在 streamstats 为事件计算运行指标之前重置所有累积的统计信息。如果与 window 一起使用,窗口也会被重置。语法:reset_before="(<eval-expression>)"。默认值为 false
reset_after 可选 eval-expression 求值为 true 时,在 streamstats 为事件计算运行指标之后重置所有累积的统计信息。该表达式可以引用 streamstats 返回的字段。如果与 window 一起使用,窗口也会被重置。语法:reset_after="(<eval-expression>)"。默认值为 false
<by-clause> 可选 用于分组的字段和表达式,包括标量函数和聚合函数。span 子句可用于按间隔将特定字段拆分为桶。语法:by [span-expression,] [field,]... 如果未指定,则所有事件作为单个组处理,并计算整个事件流的运行统计信息。
<span-expression> 可选 按间隔将字段拆分为桶(最多一个)。语法:span(field_expr, interval_expr)。默认情况下,间隔使用字段的默认单位。对于日期/时间字段,聚合结果忽略空值。示例:span(age, 10) 创建 10 岁的年龄桶,span(timestamp, 1h) 创建小时桶。有效时间单位为毫秒 (ms)、秒 (s)、分钟 (m)、小时 (h)、天 (d)、周 (w)、月 (M)、季度 (q)、年 (y)。

聚合函数

streamstats 命令支持以下聚合函数:

  • COUNT – 值的计数

  • SUM – 数值的总和

  • AVG – 数值的平均值

  • MAX – 最大值

  • MIN – 最小值

  • VAR_SAMP – 样本方差

  • VAR_POP – 总体方差

  • STDDEV_SAMP – 样本标准差

  • STDDEV_POP – 总体标准差

  • DISTINCT_COUNT/DC – 值的去重计数

  • EARLIEST – 按时间戳最早的值

  • LATEST – 按时间戳最新的值

示例 1:按组计算字段的运行平均值、运行总和和运行计数

以下查询按 gender 分组,计算所有账户的年龄运行平均值、年龄运行总和以及事件运行计数:

source=accounts
| streamstats avg(age) as running_avg, sum(age) as running_sum, count() as running_count by gender

该查询返回以下结果:

| account_number | firstname | address | balance | gender | city | employer | state | age | email | lastname | running_avg | running_sum | running_count | | — | — | — | — | — | — | — | — | — | — | — | — | — | — | | 1 | Amber | 880 Holmes Lane | 39225 | M | Brogan | Pyrami | IL | 32 | amberduke@pyrami.com | Duke | 32.0 | 32 | 1 | | 6 | Hattie | 671 Bristol Street | 5686 | M | Dante | Netagy | TN | 36 | hattiebond@netagy.com | Bond | 34.0 | 68 | 2 | | 13 | Nanette | 789 Madison Street | 32838 | F | Nogal | Quility | VA | 28 | null | Bates | 28.0 | 28 | 1 | | 18 | Dale | 467 Hutchinson Court | 4180 | M | Orick | null | MD | 33 | daleadams@boink.com | Adams | 33.666666666666664 | 101 | 3 |

示例 2:计算 2 行窗口上的运行最大值

以下查询计算 2 行窗口上的年龄运行最大值,不包括当前事件:

source=state_country
| streamstats current=false window=2 max(age) as prev_max_age

该查询返回以下结果:

| name | country | state | month | year | age | prev_max_age | | — | — | — | — | — | — | — | | Jake | USA | California | 4 | 2023 | 70 | null | | Hello | USA | New York | 4 | 2023 | 30 | 70 | | John | Canada | Ontario | 4 | 2023 | 25 | 70 | | Jane | Canada | Quebec | 4 | 2023 | 20 | 30 | | Jim | Canada | B.C | 4 | 2023 | 27 | 25 | | Peter | Canada | B.C | 4 | 2023 | 57 | 27 | | Rick | Canada | B.C | 4 | 2023 | 70 | 57 | | David | USA | Washington | 4 | 2023 | 40 | 70 |

示例 3:全局窗口与按组分隔窗口的比较

global 参数取以下值:

  • true:全局窗口应用于所有行,但窗口内的计算仍遵循 by 组。

  • false:窗口本身是按组创建的,意味着每个组都有一个独立的窗口。

以下示例使用包含以下数据的样本索引:

name country state month year age
Jake USA California 4 2023 70
Hello USA New York 4 2023 30
John Canada Ontario 4 2023 25
Jane Canada Quebec 4 2023 20
Jim Canada B.C 4 2023 27
Peter Canada B.C 4 2023 57
Rick Canada B.C 4 2023 70
David USA Washington 4 2023 40

以下示例使用不同的 global 参数,计算按国家/地区分组的账户年龄运行平均值。

global=true 时,窗口按输入顺序在所有行上滑动,但聚合仍按 country 计算。滑动窗口大小为 2

source=state_country
| streamstats window=2 global=true avg(age) as running_avg by country

因此,在全局跨所有行计算 running_avg 时,DavidRick 被包含在同一滑动窗口中:

| name | country | state | month | year | age | running_avg | | — | — | — | — | — | — | — | | Jake | USA | California | 4 | 2023 | 70 | 70.0 | | Hello | USA | New York | 4 | 2023 | 30 | 50.0 | | John | Canada | Ontario | 4 | 2023 | 25 | 25.0 | | Jane | Canada | Quebec | 4 | 2023 | 20 | 22.5 | | Jim | Canada | B.C | 4 | 2023 | 27 | 23.5 | | Peter | Canada | B.C | 4 | 2023 | 57 | 42.0 | | Rick | Canada | B.C | 4 | 2023 | 70 | 63.5 | | David | USA | Washington | 4 | 2023 | 40 | 40.0 |

相比之下,当 global=false 时,每个 by 组形成一个独立的流和窗口:

source=state_country
| streamstats window=2 global=false avg(age) as running_avg by country

DavidHelloUSA 组形成一个窗口。因此,对于 Davidrunning_avg35.0,而不是前一种情况下的 40.0

| name | country | state | month | year | age | running_avg | | — | — | — | — | — | — | — | | Jake | USA | California | 4 | 2023 | 70 | 70.0 | | Hello | USA | New York | 4 | 2023 | 30 | 50.0 | | John | Canada | Ontario | 4 | 2023 | 25 | 25.0 | | Jane | Canada | Quebec | 4 | 2023 | 20 | 22.5 | | Jim | Canada | B.C | 4 | 2023 | 27 | 23.5 | | Peter | Canada | B.C | 4 | 2023 | 57 | 42.0 | | Rick | Canada | B.C | 4 | 2023 | 70 | 63.5 | | David | USA | Washington | 4 | 2023 | 40 | 35.0 |

示例 4:条件统计信息重置

以下查询计算按国家/地区分组的账户年龄运行平均值,并应用重置:

source=state_country
| streamstats current=false reset_before=age>34 reset_after=age<25 avg(age) as avg_age by country

该查询返回以下结果:

| name | country | state | month | year | age | avg_age | | — | — | — | — | — | — | — | | Jake | USA | California | 4 | 2023 | 70 | null | | Hello | USA | New York | 4 | 2023 | 30 | 70.0 | | John | Canada | Ontario | 4 | 2023 | 25 | null | | Jane | Canada | Quebec | 4 | 2023 | 20 | 25.0 | | Jim | Canada | B.C | 4 | 2023 | 27 | null | | Peter | Canada | B.C | 4 | 2023 | 57 | null | | Rick | Canada | B.C | 4 | 2023 | 70 | null | | David | USA | Washington | 4 | 2023 | 40 | null |

示例 5:空值桶行为

bucket_nullable=false 时,空值从分组聚合中排除:

source=accounts
| streamstats bucket_nullable=false count() as cnt by employer
| fields account_number, firstname, employer, cnt

by 字段为 null 的行被排除在聚合之外,因此 Dalecntnull

| account_number | firstname | employer | cnt | | — | — | — | — | | 1 | Amber | Pyrami | 1 | | 6 | Hattie | Netagy | 1 | | 13 | Nanette | Quility | 1 | | 18 | Dale | null | null |

bucket_nullable=true 时,空值被视为有效组:

source=accounts
| streamstats bucket_nullable=true count() as cnt by employer
| fields account_number, firstname, employer, cnt

因此,Dalecnt 被包含在内并正常计算:

| account_number | firstname | employer | cnt | | — | — | — | — | | 1 | Amber | Pyrami | 1 | | 6 | Hattie | Netagy | 1 | | 13 | Nanette | Quility | 1 | | 18 | Dale | null | 1 |