:orphan:
streamstats
streamstats 命令用于在按顺序处理事件时计算累积或滚动统计信息。与一次性对整个数据集进行操作的 stats 或 eventstats 不同,streamstats 以增量方式处理事件,使其适用于时间序列和基于序列的分析。
主要特性包括支持 window(滑动窗口计算)和 current(是否在计算中包含当前事件)参数,以及专门用例,例如识别趋势或检测事件序列中的变化。
比较 stats、eventstats 和 streamstats
stats、eventstats 和 streamstats 命令都可以生成如平均值、总和和最大值等聚合。然而,它们在操作方式和产生的结果上有所不同。下表总结了这些差异。
| 方面 | 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)。当为 false 且 window 非零时,对 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 时,David 和 Rick 被包含在同一滑动窗口中:
| 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
David 和 Hello 为 USA 组形成一个窗口。因此,对于 David,running_avg 为 35.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 的行被排除在聚合之外,因此 Dale 的 cnt 为 null:
| 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
因此,Dale 的 cnt 被包含在内并正常计算:
| account_number | firstname | employer | cnt | | — | — | — | — | | 1 | Amber | Pyrami | 1 | | 6 | Hattie | Netagy | 1 | | 13 | Nanette | Quility | 1 | | 18 | Dale | null | 1 |