3 触发器表达式

概述

本页介绍触发器表达式的语法和求值细节。

简单表达式的语法为:

function(/host/item,time_period)<operator><constant>

在该表达式中,第一个操作数(位于运算符左侧)是一个带有括号中参数函数(通常为数据监控项和时间周期)。

该函数用于分析设定时间周期内接收到的数据,并得出一个计算值。

然后使用运算符将该值与第二个操作数进行比较。在此示例中,第二个操作数是一个常量,但也可以是另一个函数。

例如:

min(/Zabbix server/net.if.in[eth0,bytes],5m)>100K

如果在最近五分钟内,eth0 上接收的字节数始终大于 100 KB,则该触发器会触发。在这种情况下,表达式为真,并会创建一个问题。

触发器表达式非常灵活。在更复杂的表达式中,可以组合多个函数、运算符和常量。

另请参见:

函数

函数可用于分析已采集的值,例如计算平均值或查找特定字符串。

点击相应的函数组可查看更多详细信息。

函数组 函数
聚合函数 avg, bucket_percentile, count, histogram_quantile, item_count, kurtosis, mad, max, min, skewness, stddevpop, stddevsamp, sum, sumofsquares, varpop, varsamp
Foreach 函数 avg_foreach, bucket_rate_foreach, count_foreach, exists_foreach, last_foreach, max_foreach, min_foreach, sum_foreach
按位函数 bitand, bitlshift, bitnot, bitor, bitrshift, bitxor
日期和时间函数 date, dayofmonth, dayofweek, now, time
历史函数 change, changecount, count, countunique, find, first, firstclock, fuzzytime, last, lastclock, logeventid, logseverity, logsource, logtimestamp, monodec, monoinc, nodata, percentile, rate
趋势函数 baselinedev, baselinewma, trendavg, trendcount, trendmax, trendmin, trendstl, trendsum
数学函数 abs, acos, asin, atan, atan2, avg, cbrt, ceil, cos, cosh, cot, degrees, e, exp, expm1, floor, log, log10, max, min, mod, pi, power, radians, rand, round, signum, sin, sinh, sqrt, sum, tan, truncate
运算符函数 between, in
预测函数 forecast, timeleft
字符串函数 ascii, bitlength, bytelength, char, concat, insert, jsonpath, left, length, ltrim, mid, repeat, replace, right, rtrim, trim, xmlxpath

除非另有说明,这些函数支持用于:

Foreach 函数仅支持用于聚合计算

通常,函数返回数值以供比较。 当返回字符串时,可使用 =<> 运算符进行比较(请参见检测不同主机上的不匹配软件示例)。

函数参数

函数参数允许指定:

  • 用于引用主机监控项历史记录的监控项键(格式为 /host/key
  • 时间周期(以及其他特定于函数的参数)
  • 其他表达式
监控项键值

被引用的监控项必须处于受支持状态(nodata() 函数除外,它也会对不受支持的监控项进行计算)。

在第一个参数中省略主机名(即如 function(//key,parameter,...))仅在特定上下文中受支持:

  • 在计算型监控项的公式中
  • 在表达式宏中,可用于:

在这些上下文中,您还可以使用 {HOST.HOST} 宏。
事件名称 字段和“触发器”地图元素中,可以使用 {HOST.HOST<1-9>} 来引用触发器表达式中的特定监控项。
当在这些上下文中省略主机名或用 {HOST.HOST} 替换时,该引用将指向触发器表达式中的第一个监控项,或图形中的第一个监控项。
在这些受支持的上下文之外,在触发器表达式中省略主机名将导致错误。
有关在事件名称宏中使用双斜杠的示例,请参见 比较长期 CPU 负载

时间段

函数专用参数放在监控项键值之后,并通过逗号与监控项键值分隔。

大多数数值函数都接受时间段作为参数。 它用于指定我们感兴趣的时间区间。 可以将其指定为时间段(30s、10m、1h),也可以指定为取值范围(#5 - 表示最近五个值)。

你可以使用秒或时间后缀来表示时间段。 如果参数前带有井号,其含义则不同:

Expression Description
sum(/host/key,10m) 最近 10 分钟内各值的总和。
sum(/host/key,#10) 最近十个值的总和。

对于函数 last,带井号的参数含义又有所不同——它表示前第 N 个值。因此,给定值 30、70、20、60、50(从最近到最早):

  • last(/host/key,#2) 将返回“70”
  • last(/host/key,#5) 将返回“50”

时间段是截至“now”来计算的——其中“now”是触发器最近一次重新计算的时间(参见计算频率);“now”并不是服务器的当前时间。

时间段指定以下两者之一:

  • 考虑“now-time period”到“now”之间的所有值(或者,在使用 时间偏移时,考虑“now-time shift-time period”到 “now-time_shift”之间的所有值)
  • 考虑从过去到“now”为止、不超过 num count 个值
    • 如果在指定的时间段或 num count 内没有 0 个可用值, 则使用此函数的触发器或计算型监控项将变为不支持状态

请注意:

  • 如果触发器中只使用了单个函数(引用历史数据),则“now”始终是最近一次接收到的值。例如,如果最后一个值是在一小时前接收到的,则时间段将被视为截至一小时前的最新值。
  • 新触发器会在接收到第一个值后立即计算(历史函数);对于日期和时间函数以及nodata()函数,则会在 30 秒内计算。因此,即使自触发器创建以来,设定的时间段(例如一小时)可能尚未过去,触发器仍会被计算。即使时间范围被设置为例如最近十个值,触发器也会在接收到第一个值后进行计算。
时间偏移

支持将可选的时间偏移与时间或值计数一起作为函数参数使用。 该参数允许引用过去某一时间段内的数据。

时间偏移以 now 开始——表示当前时间,后跟 +N<time unit>-N<time unit>——用于增加或减少 N 个时间单位。

例如,avg(/host/key,1h:now-1d) 将返回一天前某一小时内的平均值。

以月(M)和年(y)指定的时间偏移仅支持趋势函数。其他函数支持秒(s)、分钟(m)、小时(h)、天(d)和周(w)。

带绝对时间段的时间偏移

时间偏移参数支持绝对时间段,例如,一天中的午夜到午夜、一周中的周一到周日、一个月中的第一天到最后一天。

绝对时间段的时间偏移以 now 开始——表示当前时间,后面可以跟任意数量的时间运算:/<time unit>——定义该时间单位的开始和结束,例如一天中的午夜到午夜;+N<time unit>-N<time unit>——用于增加或减少 N 个时间单位。

请注意,时间偏移的值可以大于或等于 0,而时间段的最小值为 1。

参数 描述
1d:now/d 昨天
1d:now/d+1d 今天
2d:now/d+1d 最近 2 天
1w:now/w 上周
1w:now/w+1w 本周
其他表达式

函数参数可以包含其他表达式,如以下语法所示:

min(min(/host/key,1h),min(/host2/key2,1h)*10)

请注意,如果函数引用了监控项历史数据,则不能使用其他表达式。 例如,以下语法允许:

min(/host/key,#5*10)

虽然在触发器中,将其他触发器表达式用作函数参数时仅限于非历史函数,但此限制不适用于计算型监控项

运算符

以下运算符可用于触发器(按执行优先级降序排列)

优先级 运算符 定义 未知值说明 将操作数强制转换为 float 1
1 - 一元负号 -Unknown → Unknown
2 not 逻辑非 not Unknown → Unknown
3 * 乘法 0 * Unknown → Unknown
(是的,结果是 Unknown,而不是 0——这样可避免在算术运算中丢失
Unknown)
1.2 * Unknown → Unknown
/ 除法 Unknown / 0 → error
Unknown / 1.2 → Unknown
0.0 / Unknown → Unknown
4 + 算术加法 1.2 + Unknown → Unknown
- 算术减法 1.2 - Unknown → Unknown
5 < 小于。该运算符定义为:

A<B ⇔ (A<B-0.000001)
1.2 < Unknown → Unknown
<= 小于或等于。该运算符定义为:

A<=B ⇔ (A≤B+0.000001)
Unknown <= Unknown → Unknown
> 大于。该运算符定义为:

A>B ⇔ (A>B+0.000001)
>= 大于或等于。该运算符定义为:

A>=B ⇔ (A≥B-0.000001)
6 = 等于。该运算符定义为:

A=B ⇔ (A≥B-0.000001) and (A≤B+0.000001)
1
<> 不等于。该运算符定义为:

A<>B ⇔ (A<B-0.000001) or (A>B+0.000001)
1
7 and 逻辑与 0 and Unknown → 0
1 and Unknown → Unknown
Unknown and Unknown → Unknown
8 or 逻辑或 1 or Unknown → 1
0 or Unknown → Unknown
Unknown or Unknown → Unknown

1 在以下情况下,字符串操作数仍会被转换为数值:

  • 另一个操作数是数值
  • 对操作数使用了 =<> 以外的运算符

(如果转换失败,则数值操作数会被转换为字符串操作数,并将两个操作数作为字符串进行比较。)

notandor 运算符区分大小写,且必须使用小写。 它们还必须由空格或括号包围。

除一元 -not 外,所有运算符都具有从左到右的结合性。 一元 -not 是非结合的(这意味着应使用 -(-1)not (not 1),而不是 --1not not 1)。

求值结果:

  • <<=>>==<> 运算符在指定关系为真时,应在触发器表达式中产生“1”,为假时产生“0”。 如果至少有一个操作数为 Unknown,则结果为 Unknown;
  • 对于已知操作数,and 在其两个操作数都不等于“0”时产生“1”;否则产生“0”;对于未知操作数,and 仅当其中一个操作数等于“0”时产生“0”;否则产生“Unknown”;
  • 对于已知操作数,or 在其任一操作数不等于“0”时产生“1”;否则产生“0”;对于未知操作数,or 仅当其中一个操作数不等于“0”时产生“1”;否则产生“Unknown”;
  • 对于已知操作数,逻辑非运算符 not 的结果为:如果其操作数的值不等于“0”,则为“0”;如果其操作数的值等于“0”,则为“1”。 对于未知操作数,not 产生“Unknown”。

未知表达式状态

在以下情况下,触发器表达式中可能会出现未知操作数:

  • 使用了不受支持的监控项
  • 对于受支持的监控项,函数求值结果出错

在这种情况下,触发器表达式通常会被求值为 Unknown(因为它无法被计算)。

可以对未知触发器接收通知

例外情况

尽管存在未知操作数,在某些情况下,触发器表达式仍可被求值为已知结果(Problem/OK):

  • 无论被引用的监控项是否受支持,nodata() 函数都会被求值。
  • 包含 AND/OR 的表达式在两种情况下可被求值为已知结果:
    • 情况 11 or some_function(unsupported_item1) or some_function(unsupported_item2) or ... 会被求值为已知结果(1 或“Problem”);
    • 情况 20 and some_function(unsupported_item1) and some_function(unsupported_item2) and ... 会被求值为已知结果(0 或“OK”)。
  • 如果对受支持监控项的函数求值结果出错,则该函数值会变为 Unknown,并在后续表达式求值中作为未知操作数参与计算。

如上所述,未知操作数只可能在逻辑表达式中“消失”。 在算术表达式中,未知操作数始终会导致结果为 Unknown(除以 0 的情况除外)。

未知表达式状态不会改变触发器状态(Problem/OK)。 因此,如果触发器状态原本为“Problem”(见情况 1),即使已知部分已恢复(1 变为 0),它仍会保持 problem 状态,因为此时表达式会被求值为 Unknown,而这不会改变触发器状态。

如果包含多个不受支持监控项的触发器表达式被求值为 Unknown,则前端中的错误消息会指向最后一个被求值的不受支持监控项。

值缓存

触发器求值所需的值由 Zabbix 服务器缓存。 因此,在服务器重启后的一段时间内,触发器求值会导致数据库负载升高。

当监控项历史值被删除时(无论是手动删除还是由 housekeeper 删除),值缓存都不会被清除,因此服务器将继续使用缓存的值,直到这些值早于触发器函数中定义的时间段,或者服务器被重启。

如果缓存中没有最近的数据,并且函数中未定义查询时间段,Zabbix 默认会向过去最多回溯一周,从数据库中查询历史值。