OpenTelemetry OTTL 必知必会

OpenTelemetry OTTL 必知必会

好的!既然你来到这里,说明你对 OpenTelemetry (OTel) 已经有了必定的了解,并且想学习如何提高数据的容量和质量。(或者,你只是想了解一下 OpenTelemetry 转换语言,即 OTTL。一步步来,我懂你。)根据你的业务侧重点不同,提高数据容量和质量的方法有许多,但一般我们关注的是 过滤和规范化数据 ,以及**删除个人身份信息 (PII)**。

这些操作都可以通过 collector-contrib 自带的专用处理器(purpose-built processors)来完成,那么 OTTL 的用武之地在哪里呢?实际上,其中一些组件正是由 OTTL 驱动的。OTel 让你能够处理那些需要跨字段逻辑(cross-field logic)条件控制(conditionality)的任务——这些是今天不使用 OTTL 就无法做到的。仅凭这几个粗体字,你可能就已经被 OTTL 吸引了;如果还没有,请做好准备,由于你很快就会被它折服。

注意 :为了充分利用 OTTL,在开始转换数据之前,最好先具备一些 OTel 的先期知识或经验,了解三种主要的信号类型(traces、metrics 和 logs),并理解你目前的系统所生成的遥测数据。

什么是 OTTL?

Collector 组件中的 OTTL

在深入了解 OTTL 是什么 之前,先了解它在 Collector 内部的 位置 会有所协助。OTTL 驱动着黑框中高亮的组件: Filter(过滤) 、Transform(转换)和 Tail Sampling(尾部采样)处理器,以及 Routing(路由)和 Count(计数)连接器:

OpenTelemetry OTTL 必知必会 Collector 组件架构图

你最常使用 OTTL 的两个地方是:

  • **Filter 处理器 (Filter processor)**:这是你的门禁;使用 OTTL 布尔表达式来评估传入的数据,并有选择地丢弃符合(或不符合)你标准的 span、日志记录或其他数据点。

  • **Transform 处理器 (Transform processor)**:这是你进行数据变更的主要组件,从插入新属性、提取子字符串,到对指标进行算术运算等等。

作为领域特定语言的 OTTL

OTTL 是一种**领域特定语言 (DSL)**,这仅仅意味着它是专门为特定应用领域设计的;在这种情况下,它的目标是处理 Collector 中的数据。它提供了一种单一且一致的语法,可与 OTel 原生概念和结构进行交互,让你能够编写准确的、定制化的语句来转换、过滤和操纵你的指标、日志和追踪。

以下是 Collector 配置的片段,其中为 transform 处理器配置了一条 OTTL 语句(稍后我们将拆解其语法并探索它的作用):

transform:
trace_statements:
-set(span.attributes["user.id"],span.attributes["userId"])
wherespan.attributes["user.id"]==nil

近期文章:

  • 28 个系统设计概念:它们解决了哪些生产问题?

  • “日抛型软件”不是软件,而是用户层的临时胶水

  • AI SRE 第一步是收集事件上下文

  • OpenLIT SDK 与 VictoriaMetrics 可观测性栈:面向 LLM 应用和 Agent 的可观测性

  • Flashcat 6 月新版:AI Native 能力系统化演进

  • 告警发到群里,不等于故障有人负责

为什么使用 OTTL?

易用性(相对而言)

那么“OTTL 作为 DSL”对你意味着什么?许多东西!由于它类似于流行的编程语言(即 Python、Go 和 JavaScript),所以对许多开发者来说它的学习曲线较低,自带许多内置函数,并且比 YAML 更易于编写、修改和阅读(当然,实际效果因人而异)。它还能让你的 Collector 配置更加紧凑。

OTTL 具有极强的表现力

不过,OTTL 的真正威力在于它 解锁了你在标准配置中根本无法表达的操作 ,包括设置条件。这超级重大!由于这意味着 你可以根据遥测数据的上下文、内容或属性,有选择地应用数据转换

Collector 附带了许多处理器,包括超级实用的 attributes resource 处理器,它们可以处理各种常见的操作。不过,由于这些组件一般是专门定制的(purpose-built),所以它们仅限于那些单一的用途。当你需要更有表现力的东西时——例如,如果你需要应用条件,或者需要提升一个嵌套属性——就需要 OTTL 来救场了。

有哪些是 OTTL 能做到而专用处理器做不到的?

简短的答案就在上一小节中,但让我们来看一些具体的例子。

重命名现有属性

你可以使用 attributes 处理器来重命名现有属性:

attributes:
actions:
-key:userId
new_key:user.id
action:rename

或者,你可以使用 transform 处理器并编写 OTTL 语句来做同样的事情:

transform:
trace_statements:
-set(span.attributes["user.id"],span.attributes["userId"])
-delete_key(span.attributes,"userId")

但如果你想 基于某些条件 来重命名属性呢?例如, 仅当 目标属性尚不存在时才重命名?列如你正在从旧的属性名称迁移,但某些服务已经更新了,你只想在新键不存在时才进行重命名。

在这种情况下,使用 attributes 处理器你就无能为力了,由于它根本无法处理条件逻辑。一旦你需要条件控制,就必须引入 OTTL:

transform:
trace_statements:
-set(span.attributes["user.id"],span.attributes["userId"])
wherespan.attributes["user.id"]==nil
-delete_key(span.attributes,"userId")where
span.attributes["user.id"]!=nil

脱敏或修改 PII(个人身份信息)

如果你只是想删除 PII,你可以使用 attributes 处理器彻底删除该键,但你无法掩码或替换其值。而使用 OTTL,你可以在保留键的同时修改其值(这一般也是合规性要求真正要求的):

transform:
trace_statements:
-replace_pattern(span.attributes["user.email"],".+@.+\..+",
"[redacted]")

派生属性值

如果你想在运行时从另一个字段派生属性值, attributes 处理器 勉强 可以做到,但只能是无条件的,且只能在一样的上下文中:

attributes:
actions:
-key:service.owner
from_attribute:team
action:insert

使用 OTTL,你可以有条件地派生值,并在同一个配置块中跨 span 和 resource 属性进行操作。你还可以使用 OTTL 来提升嵌套属性:

transform:
trace_statements:
-set(span.attributes["service.owner"],span.attributes["team"])
wherespan.attributes["service.owner"]==nil
-set(resource.attributes["deployment.environment"],
"production")where
resource.attributes["deployment.environment"]==niland
resource.attributes["service.name"]=="payment-service"

规范化不一致的值

如果你想规范化不一致的值,例如不同团队对环境名称的拼写不同,OTTL 支持的模式匹配(pattern matching)会超级有用( attributes 处理器不支持模式匹配或值检查)。

以下是不同团队以多种方式拼写不同环境的示例;OTTL 在流水线中将其修复:

transform:
trace_statements:
-set(resource.attributes["deployment.environment"],
"production")where
IsMatch(resource.attributes["deployment.environment"],
"^(prod|production|prd)$")
-set(resource.attributes["deployment.environment"],"staging")
whereIsMatch(resource.attributes["deployment.environment"],
"^(staging|stage|stg)$")

OTTL 还能做什么?

标准处理器会无条件应用转换,但 OTTL 的 where 子句允许你将任何操作绑定在运行时条件上,例如:“仅在另一个属性为 nil 时才重命名此属性”,“仅在 这两个 条件都满足时才丢弃此 span”。

OTTL 还允许你:

  • 使用基于正则的匹配或替换 replace_pattern IsMatch 函数仅在 OTTL 中可用。

  • 运行跨字段操作 :将值从一个属性复制到另一个属性、将 span 属性提升到 resource 级别,或者根据不同字段的值来设置某个字段,这些都需要 OTTL。

  • 在单次处理中链式执行多个操作 :OTTL 允许你在单个处理器块中按顺序排列多个转换,它们会自上而下进行评估。

  • 在特定的上下文级别进行操作 :如果你需要对单个数据点(data points)而不是整个指标工具(metric instrument)进行操作,或者对 span 事件(span events)而不是 span 进行操作,你就需要 OTTL;标准处理器没有暴露那么细的粒度。

如何使用 OTTL?

语法与核心概念

开始使用 OTTL 意味着编写转换语句,并将它们附加到 OTel Collector 配置中相应的由 OTTL 驱动的处理器(transform、filter 或 tail sampling 处理器)上。

一条 OTTL 语句由两部分组成:

  1. 一个用于转换遥测数据的**函数 (function)**。

  2. (可选)一个决定该函数是否执行的**条件 (condition)**。

让我们拆解一下之前看过的这个示例语句:

set(span.attributes["user.id"], span.attributes["userId"]) where span.attributes["user.id"] == nil

这里的函数是 set ,当 span 上的属性 user.id 为 nil 或不存在时,它使用第二个参数 userId 的值来设置第一个参数 user.id 的值。

OTTL 函数分为两种类型:

  • Editors(编辑器) :它们会转换遥测数据(因此可能会产生副作用),可能会返回值(尽管这既非必需也不常见),并且以小写字母开头。例如: append , delete_index , delete_key , truncate_all

  • Converters(转换器) :它们接受一个输入参数并生成一个输出,总是返回值,并且以大写字母开头。例如: Bool , Decode , Concat , ConvertCase

回到我们的示例语句:在 set 函数内部,我们使用路径 span.attributes 来访问 span 的属性。OTel 信号的每个字段都有一个**路径 (Path)**,它让你能够定位想要读取或修改的遥测数据中的特定元素。以下是其他遥测类型路径的一些示例:

  • metric.name

  • resource.name

  • resource.attributes["key"]

  • log.severity_text

路径表达式的第一部分是**上下文 (context)**(在我们的例子中,上下文是 span ),它直接映射到 OTel 信号以及更高层级的结构(如 resource 和 instrumentation scope):

  • Resource

  • Instrumentation Scope

  • Span

  • Span Event

  • Metric

  • Datapoint

  • Log

  • Profile

亲自动手试一试!

Elastic 的朋友们制作了一个超级酷的工具,你可以用它来验证你的 OTTL 语句,叫做 OTTL Playground ,可以通过 ottl.run 访问。它包含了示例 Payload 和示例语句,你也可以输入自己的 Payload 和语句。玩起来相当有趣!

OpenTelemetry OTTL 必知必会 OTTL Playground 界面

基础故障排查

一个基础的排查技巧是在 Collector 中启用**调试日志 (debug logging)**,以打印出应用转换语句之前和之后的数据长什么样:

service:
telemetry:
logs:
level:debug

它的输出超级冗长,但你可以通过 grep 过滤你想要的日志来缩小范围:

docker compose logs -f collector 2>&1 | grep -i "transformcontext|condition matched"

常见陷阱

在开始编写 OTTL 语句时,有几点需要注意:

  • 语句顺序至关重大 :OTTL 在上下文块中是自上而下评估语句的。如果语句 B 依赖于语句 A 设置的值,则 A 必须排在前面。同样,如果你在语句 A 中删除了一个键,语句 B 将无法读取它。

  • 先用 debug exporter(或 OTTL Playground!)进行测试 :在部署到生产环境之前,务必针对真实流量验证你的转换。带有详细度(detailed verbosity)的 debug exporter 可以为你提供数据转换前后的完整视图。

  • 注意正则的复杂度 :在 replace_pattern 调用中使用复杂的正则表达式会增加 CPU 开销,尤其是在高吞吐量的情况下。在将重度依赖正则的转换部署到生产管线之前,请先在负载下对 Collector 进行性能分析(Profile)。

  • 目前,OTTL 不支持跨信号交互 ,这意味着以下语句将 无法 正常工作:

    set(span.attributes["log body"], log.body)

原文:Devs, Transform Your Data! OTTL Roll Out! https://www.linkedin.com/pulse/devs-transform-your-data-ottl-roll-out-reese-lee-wlv9c/

© 版权声明

相关文章

1 条评论

none
暂无评论...