使用通用表达式语言

通用表达式语言 (CEL) 是一种开源的非图灵完备语言,可用于对表达式求值。Eventarc Advanced 中的每次注册都包含一个以 CEL 编写的条件表达式,用于评估和过滤消息。在 Eventarc Advanced 中,您还可以使用 CEL 执行以下操作:

  • 通过将 CEL 条件表达式应用于事件上下文属性来控制发布访问权限

  • 使用 CEL 编写转换表达式,转换事件数据内容

通常,条件表达式由一个或多个使用逻辑运算符(&&、|| 或 !)联接的语句组成。每个语句表示一条适用于数据的基于属性的规则。最常见的情况是,使用运算符将变量中包含的值与字面量值进行比较。

例如,如果 message.type 的值为 google.cloud.dataflow.job.v1beta3.statusChanged,则表达式 message.type == "google.cloud.dataflow.job.v1beta3.statusChanged" 的求值结果为 True。

详情请参阅以下内容:

可用的属性

所有事件上下文属性都可以通过预定义的 message 对象作为变量进行访问。这些变量会在运行时根据事件上下文属性填充值。注册可以使用变量来表示给定的属性。例如,message.type 会返回 type 属性的值。

请注意以下几点:

  • 活动可以包含任意数量的其他自定义 CloudEvents 属性(也称为扩展属性),并且注册可以使用这些属性,但这些属性的名称必须各不相同。 不过,无论其实际格式如何,在 CEL 表达式中都表示为 String 类型。您可以使用 CEL 表达式将其值转换为其他类型。

  • 您无法根据事件载荷内容评估注册情况或控制发布访问权限。message.data 和 message.data_base64 均为预留变量,不能在表达式中使用。不过,在转换事件数据时,系统支持 CEL,这让您可以修改事件载荷内容(例如,满足特定目标位置的 API 合约)。

评估条件表达式时可以访问以下属性:

属性 属性类型 说明
message.datacontenttype String data 值的内容类型
message.dataschema URI 标识 data 所遵循的架构
message.id String 用于标识事件;提供方必须确保 source + id 对于每个不同的事件都是唯一的
message.source URI-reference 标识事件发生的上下文
message.specversion String 事件使用的 CloudEvents 规范版本
message.subject String 描述事件在事件提供方(由 source 标识)上下文中的主题
message.time Timestamp 发生事件的时间戳;可能会由 CloudEvents 生产者设置为其他时间(例如当前时间);不过,同一 source 的所有生产者必须保持一致
message.type String 描述与原始事件相关的事件类型;请参阅 Eventarc 支持的 Google 事件类型

运算符和函数

您可以使用运算符和函数来构建复杂的逻辑表达式。

借助 &&、|| 和 ! 等逻辑运算符,您可以在条件表达式中验证多个变量。例如,message.time.getFullYear() < 2020 && message.type == "google.cloud.dataflow.job.v1beta3.statusChanged" 连接了两个语句,而且必须同时满足这两个语句(即这两个语句均为 True),才能生成总体结果 True。

字符串操作运算符(例如 x.contains('y'))可匹配您定义的字符串或子字符串,并让您开发规则来匹配消息,而无需列出每种可能的组合。

Eventarc Advanced 还支持扩展函数,例如 merge 和 flatten,这些函数可用于转换数据并简化对从总线接收的事件的修改。

请参阅 CEL 预定义运算符和函数以及 CEL 预定义宏的列表。

逻辑运算符

下表介绍了 Eventarc Advanced 支持的逻辑运算符。

表达式 说明
x == "my_string" 如果 x 等于常量字符串字面量实参,则返回 True。
x == R"my_string\n" 如果 x 等于不解释转义序列的指定原始字符串字面量,则返回 True。原始字符串字面量便于表示自己必须使用转义序列的字符串,例如正则表达式或程序文本。
x == y 如果 x 等于 y,则返回 True。
x != y 如果 x 不等于 y,则返回 True。
x && y 如果 x 和 y 均为 True,则返回 True。
x || y 如果 x、y 或两者均为 True,则返回 True。
!x 如果布尔值 x 为 False,则返回 True;如果布尔值 x 为 True,则返回 False。
m['k'] 如果存在键 k,则返回字符串到字符串映射 m 中键 k 处的值。如果不存在键 k,则返回一个错误,导致正在评估的规则不匹配。

字符串操作运算符

下表介绍了 Eventarc Advanced 支持的字符串操作运算符。

表达式 说明
double(x) 将 x 的字符串结果转换为 double 类型。转换后的值可用于使用标准算术运算符(例如 > 和 <=)比较浮点数。此方法仅适用于可为浮点数的值。
int(x) 将 x 的字符串结果转换为 int 类型。转换后的值可用于使用标准算术运算符(例如 > 和 <=)比较整数。这仅适用于可以为整数的值。
x + y 返回串联的字符串 xy。
x.contains(y) 如果字符串 x 包含子字符串 y,则返回 True。
x.endsWith(y) 如果字符串 x 以子字符串 y 结尾,则返回 True。
x.join() 返回一个新字符串,其中包含串联的字符串列表元素。接受一个可选的分隔符,该分隔符将放置在结果字符串中的元素之间。例如,以下表达式会返回 'hello world':

['hello', 'world'].join(' ')

x.lowerAscii() 返回一个新字符串,其中所有 ASCII 字符均为小写。
x.matches(y)

如果字符串 x 与指定的 RE2 模式 y 匹配,则返回 True。

RE2 模式在编译时使用了会停用 Unicode 特性的 RE2::Latin1 选项。

x.replace(y,z) 返回一个新字符串,其中子字符串 y 的出现次数已替换为子字符串 z。接受一个可选实参,用于限制替换次数。例如,以下表达式会返回 'wello hello':

'hello hello'.replace('he', 'we', 1)

x.split(y) 返回一个字符串列表,该列表是通过分隔符 y 将输入拆分而得到的。接受一个可选实参,用于限制要生成的子字符串数量。例如,以下表达式会返回 ['hello', 'hello hello']:

'hello hello hello'.split(' ', 2)

x.startsWith(y) 如果字符串 x 以子字符串 y 开头,则返回 True。
x.upperAscii() 返回一个新字符串,其中所有 ASCII 字符均为大写。

正则表达式函数

下表介绍了 Eventarc Advanced 支持的正则表达式函数。

表达式 说明
re.capture(target,regex)

使用 regex 捕获 target 字符串中的第一个未命名或已命名组值,并返回一个字符串。例如,以下表达式会返回 "o":

re.capture("hello", R"hell(o)")

re.captureN(target,regex) 使用 regex 从 target 字符串中捕获组名称和字符串(对于已命名的组)以及组索引和字符串(对于未命名的组),并返回键值对的映射。例如,以下表达式会返回 {"1": "user", "Username": "testuser", "Domain": "testdomain"}:

re.captureN("The user testuser belongs to testdomain", R"The (user|domain) (?P.*) belongs to (?P.*)")

re.extract(target,regex,rewrite) 使用 regex 从 target 字符串中提取匹配的组值,并返回根据 rewrite 实参格式化的提取值字符串。例如,以下表达式会返回 "example.com":

re.extract("alex@example.com", "(^.*@)(.*)", "\\2")

x.matches(regex)

如果字符串 x 与指定的 RE2 模式 regex 匹配,则返回 True。

RE2 模式在编译时使用了会停用 Unicode 特性的 RE2::Latin1 选项。

正则表达式遵循 RE2 语法。请注意,正则表达式前面的 R 表示不需要转义的原始字符串。

扩展函数

Eventarc Advanced 支持某些扩展函数,这些函数可用于转换通过总线接收的事件数据。如需了解详情和示例,请参阅转换已接收事件。

后续步骤