纲要
OTel 组件与关系映射的模式
OtelComponentMapping
每个组件映射:
-
使用条件选择遥测。
-
使用表达式提取值。
-
生成一个由稳定标识符标识的单一逻辑组件。
多个遥测记录可能解析为相同的组件标识符;在这种情况下,组件会被合并并刷新。
_type: "OtelComponentMapping"
name: string
input:
signal: ["TRACES" | "METRICS"]
resource:
condition: <cel-boolean> # default: true
action: CONTINUE # default
scope:
condition: <cel-boolean> # default: true
action: CONTINUE # default
span: # TRACES only
condition: <cel-boolean> # default: true
action: CONTINUE # default
metric: # METRICS only
condition: <cel-boolean> # default: true
action: CONTINUE # default
datapoint: # METRICS only
condition: <cel-boolean> # default: true
action: CONTINUE # default
vars: # Optional
- name: string
value: <cel-expression>
output:
identifier: <cel-string>
name: <cel-string>
typeName: <cel-string>
typeIdentifier: <cel-string> # Optional
domainName: <cel-string>
domainIdentifier: <cel-string> # Optional
layerName: <cel-string>
layerIdentifier: <cel-string> # Optional
required: # Optional (required means that if any expression fails, the mapping fails)
version: <cel-string> # Optional
additionalIdentifiers: # Optional
- <cel-string>
tags: # Optional
- source: <cel-string>
target: string
- source: <cel-string>
pattern: regex
target: string
optional: # Optional (besides being optional on the schema, optional means that if any expression under `optional` fails, the mapping will continue, but without the failed expression/field)
version: <cel-string> # Optional
additionalIdentifiers: # Optional
- <cel-string>
tags: # Optional
- source: <cel-string>
target: string
- source: <cel-map>
pattern: regex
target: string
expireAfter: duration-ms
OtelRelationMapping
每个关系映射:
-
解析一个
sourceId和一个targetId。 -
分配关系类型。
-
在现有或未来组件之间产生一个有向边。
当源组件和目标组件存在时,关系会被具体化。
_type: "OtelRelationMapping"
name: string
input:
signal: ["TRACES" | "METRICS"]
resource:
condition: <cel-boolean> # default: true
action: CONTINUE # default
scope:
condition: <cel-boolean> # default: true
action: CONTINUE # default
span: # TRACES only
condition: <cel-boolean> # default: true
action: CONTINUE # default
metric: # METRICS only
condition: <cel-boolean> # default: true
action: CONTINUE # default
datapoint: # METRICS only
condition: <cel-boolean> # default: true
action: CONTINUE # default
vars: # Optional
- name: string
value: <cel-expression>
output:
sourceId: <cel-string>
targetId: <cel-string>
typeName: <cel-string>
typeIdentifier: <cel-string> # Optional
expireAfter: duration-ms
组件与关系的身份、合并和生命周期
组件身份
output.identifier 字段定义了组件的主要身份,并且在整个拓扑中必须是 "全局" 唯一的。通过 output.required.additionalIdentifiers,您可以为组件指定更多标识符。 具有至少一个重叠标识符的组件被视为相同的逻辑实体,并由平台合并。这使得标识符的构造成为一个关键的设计选择。
标识符应:
-
遵循 SUSE® Observability 标识符(即
urn:…)格式。有关更多信息,请参阅 标识符 文档。 -
在时间上保持稳定。
-
反映预期的基数(服务、实例、数据库等)。
-
避免无界维度。
|
使用 |
输入遍历模型
拓扑映射以层次方式遍历 OpenTelemetry 数据 - resource → scope → metric/span → datapoint
每个级别可以定义:
-
一个条件:一个 CEL 布尔表达式。
-
一个动作:如果条件匹配,则执行的操作。
每个信号的可用字段
所选信号决定了哪些数据结构和属性可用于表达式评估。
TRACES
提供访问:
-
resource.attributes
-
scope.name, scope.version, scope.attributes
-
span.name, span.kind, span.statusMessage, span.statusCode, span.attributes
示例:
resource.attributes['service.name'] == 'checkout'
# OR
span.kind == 'SPAN_KIND_SERVER' && span.attributes['http.method'] == 'POST'
METRICS
提供访问:
-
resource.attributes
-
scope.name, scope.version, scope.attributes
-
metric.name, metric.description, metric.unit
-
datapoint.attributes
示例:
metric.name == 'traces_service_graph_request_total'
# OR
datapoint.attributes['connection_type'] == 'database'
条件和动作
条件
条件决定处理是否在给定级别继续。如果条件评估为假,则该遥测元素的映射将被跳过。
Defaults(默认):
-
条件默认为“真”。这允许在每个级别省略显式条件,以作为默认处理。
约束:
-
当声明多个输入信号时(例如,
TRACES`和`METRICS),表达式中的数据只能从共同祖先级别访问,在所有情况下都是作用域级别。 -
不允许从较低/子级别访问数据/字段。例如,作用域级别字段不能在资源级别访问。
-
不允许从另一个输入信号访问数据/字段。例如,度量级别字段不能从跨度级别访问,反之亦然。
条件可以访问父级的数据。例如,在跨度级别,可以访问作用域和资源级别的数据。
input:
signal:
- "TRACES"
resource:
condition: "${'service.name' in resource.attributes}"
# action omitted since the default is `CONTINUE`
scope:
action: "CREATE" # input block describes that it expects to filter until this level only
condition: "${scope.name.contains('http') && resource.attributes['service.name'] == 'cart-svc'}" # it's allowed to access resource-level fields at scope-level
行动
支持的动作:
-
继续 – 继续评估到下一个级别。
-
创建 – 在此级别创建一个组件或关系。
Defaults(默认):
-
动作默认为“继续”。
这意味着需要在输入级别显式指定`CREATE`动作,以便应用映射。
以下是一些有效输入声明的更多示例:
TRACES
input:
signal:
- "TRACES"
resource:
condition: "${'service.name' in resource.attributes}"
# action omitted since the default is `CONTINUE`
scope:
# action and condition have been omitted since the defaults are `CONTINUE` and `true` respectively
span:
action: "CREATE"
condition: "${span.attributes['http.method'] == 'POST'}"
METRICS
input:
signal:
- "METRICS"
resource:
# action and condition have been omitted since the defaults are `CONTINUE` and `true` respectively
scope:
condition: "scope.name == 'traces_service_graph'"
metric:
# action omitted since the default is `CONTINUE`
condition: "metric.name == 'traces_service_graph_request_total'"
datapoint:
action: "CREATE"
condition: |
'client' in datapoint.attributes &&
'server' in datapoint.attributes
变量(vars)
映射可以定义变量以避免重复并提高可读性。
变量:
-
使用CEL表达式进行评估。
-
可以引用输入过滤器匹配的最深输入级别中可用的任何字段。例如,如果输入选择在跨度级别具有`CREATE`操作,则可以使用资源、范围和跨度字段。
-
可以在输出字段中重复使用。
示例:
vars:
- name: "service"
value: "${resource.attributes['service.name']}"
在评估输出表达式之前解析变量。
输出
`output`部分定义了OpenTelemetry信号(跟踪/指标)应如何映射到组件或关系。
输出字段:
-
使用CEL表达式动态生成值。
-
可以引用输入过滤器匹配的最深输入级别中可用的任何字段。例如,如果输入选择在跨度级别具有`CREATE`操作,则可以使用资源、范围和跨度字段。
如果字段的值不需要动态生成,则可以在模式指定的`<cel-string>`表达式声明的位置设置字符串字面量。
必需与可选可选子部分
组件映射模式区分两种错误处理行为:
标签映射
组件映射可以定义标签映射,以丰富组件的元数据。
支持两种形式:
直接映射
- source: "value"
target: "key"
结果:key:value
- source: "${resource.attributes['service.name']}"
target: "service.name"
给定:resource.attributes { 'service.name': 'cart-svc' }
结果:service.name:cart-svc
直接映射的源需要是:
-
字符串字面量
-
字符串表达式
基于正则表达式的提取
- source: "${resource.attributes}"
pattern: "telemetry.sdk\.(.*)"
target: "telemetry.sdk.${1}"
给定:resource.attributes: { 'telemetry.sdk.language': 'go', 'telemetry.sdk.version': '1.23.1' }
结果:telemetry.sdk.language:go;telemetry.sdk.version:1.23.1
基于正则表达式的映射支持多个捕获组,可以在目标表达式中按位置引用。
基于正则表达式的映射的源需要是:
-
映射表达式
多个捕获组的示例:
- source: "${resource.attributes}"
pattern: "^(os|host|cloud|azure|gcp)\.(.*)"
target: "${1}.${2}"
在基于正则表达式的映射中,捕获组被替换到目标中。
CEL 表达式 (<cel-*>) 说明:
-
<cel-string>- 需要返回一个字符串;可以是以下之一:-
字符串字面量(例如,"hello")
-
字符串表达式,包裹在
${…}中(例如,"${resource.attributes['service.name']}") -
字符串插值(例如,"urn:opentelemetry:namespace/$\{resource.attributes['namespace']}:service/$\{resource.attributes['service.name']}") - 注意:对于字符串插值,整个表达式不包裹在
$\{…}中
-
-
cel-boolean- 需要返回一个布尔数据类型;可以是以下之一:-
布尔字面量(例如,"true")
-
布尔表达式(例如,"'namespace' in resource.attributes") - 注意:布尔表达式不被包裹在`${…}`中
-
-
cel-map- 需要返回一个映射;可以是以下之一:-
映射字面量(例如,"${{'a':1, 'b': 'two'}}")
-
映射表达式(例如,"${resource.attributes}")
-
-
cel-expression- 返回"任何"类型,可以是以下之一:-
字符串表达式
-
布尔表达式
-
映射表达式(例如,"${resource.attributes}" - 返回属性映射)
-
列表表达式(例如,"${resource.attributes['process.command_args']}" - 返回一个列表)
-
插值
字符串插值允许您在字符串字面量中嵌入表达式。虽然CEL规范不直接支持,但OTel映射配置提供了`prefix-${expression1}/suffix-${expression2}`形式的插值语法,内部重写为使用`+运算符的字符串连接(例如,`"prefix-" + expression1 + "/suffix-" + expression2)。
理解这种重写行为很重要,原因有两个:
-
不支持嵌套插值:由于字符串表达式用`${…}`标记,您不能嵌套插值表达式。但是,您可以直接使用`+`运算符编写连接。例如:
${ 'service.instance.id' in resource.attributes ? resource.attributes['service.name'] + " - " + resource.attributes['service.instance.id'] : resource.attributes['service.name'] + " - instance" } -
非字符串值需要类型转换:CEL是强类型的,在连接时不会自动转换类型。在插值不同类型的值时,您必须显式将非字符串类型转换为字符串。
例如,如果`process.pid`是一个整数(例如,
1),则此表达式将失败:${resource.attributes['service.name']}/${resource.attributes['process.pid']}正确的形式需要先将动态值转换为具体类型,然后再将其转换为字符串:
${resource.attributes['service.name']}/${string(int(resource.attributes['process.pid']))}双重转换(
string(int(…)))是必要的,因为:-
resource.attributes['process.pid']返回一个动态(dyn)类型 -
int()将动态值转换为具体的整数类型 -
string()将整数转换为字符串以进行连接对于其他类型,使用类似的模式:
string(double(…))用于浮点数,string(bool(…))用于布尔数据类型。
-
CEL 语言参考
CEL 是一种安全的、无副作用的表达式语言,旨在用于配置和策略用例。在 OpenTelemetry 拓扑映射的上下文中,CEL 用于:
-
定义决定映射是否适用的条件
-
从遥测属性计算变量
-
动态构建标识符、名称和标签
表达式在一个明确定义的、类型化的上下文中进行评估,该上下文来源于正在处理的 OpenTelemetry 信号(例如,resource、scope、span、metric 或 datapoint)。
访问 CEL 的 langdef 以获取详细参考。
像 https://playcel.undistro.io/ 这样的在线 CEL 游乐场是快速检查表达式有效性的有用工具。
常见模式和最佳实践
-
用条件保护映射,以避免意外的基数问题
-
始终以防御性方式处理缺失的属性
-
保持标识符稳定且可预测
-
对于复杂表达式,优先使用变量以提高可读性
-
根据信号频率使用适当的 expireAfter 值。
请参阅 故障排除 页面以获取有关故障排除 OTel 映射的指导。