关于 opentelemetry-ottl
面向 OpenTelemetry Collector 配置作者的 OTTL 技能,帮助编写和排查转换、过滤及路由语句。内容涵盖上下文选择、错误处理和常见遥测处理模式。
主要功能
- 01编写和调试 OTTL 语句
- 02说明信号上下文与路径表达式
- 03排查 Collector 错误模式
- 04转换、过滤及路由遥测
- 05处理基数控制与 PII 脱敏
适用场景
- 01修正 transform 处理器中的字段转换
- 02排查因上下文或类型不匹配导致的问题
- 03减少指标属性基数
- 04脱敏日志中的个人信息
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ coralogix/ cx-skills --skill opentelemetry-ottl安装后在 Claude Code 中输入/opentelemetry-ottl确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
evals/datapoint-filter-missing-tenant/capability.txtcriteria.jsontask.mdevals/delete-matching-keys-header-prefix/capability.txtcriteria.jsontask.mdevals/error-mode-propagate-vs-ignore/capability.txtcriteria.jsontask.mdevals/filter-vs-transform-dropping/capability.txtcriteria.jsontask.mdevals/first-non-nil-fallback-chain/capability.txtcriteria.jsontask.mdevals/histogram-bucket-extraction-drop/capability.txtcriteria.jsontask.mdevals/json-body-parsejson-extraction/capability.txtcriteria.jsontask.mdevals/keep-keys-ismap-guard/capability.txtcriteria.jsontask.mdevals/log-attr-to-resource-for-exporter/capability.txtcriteria.jsontask.mdevals/log-timestamp-mutation/capability.txtcriteria.jsontask.md详细介绍
OTTL
OpenTelemetry Transformation Language(OTTL)可在不修改应用代码的情况下,在 OTel Collector 管道中转换、过滤和路由遥测数据。编写或调试 transform processor、filter processor 或 routing connector 中的 OTTL 语句时,请加载此技能。
何时使用此技能
| 用例 | 操作 |
|---|---|
| 有条件地更改值或字段 | 使用正确上下文的 transform processor |
| 完全丢弃遥测数据(匹配 = 丢弃) | filter processor |
| 为所有资源设置静态属性 | 使用 resource processor — 比 OTTL 更简单 |
| 将资源字段复制到 span 或日志中 | 使用正确上下文的 transform |
| 将遥测数据路由到不同管道 | routing connector |
| 降低指标或 trace 的基数 | 使用 keep_keys / delete_matching_keys 的 transform → references/cardinality.md |
| 将直方图的 _sum/_count 提取为独立指标,然后丢弃直方图 | 在 context: metric 中使用 extract_sum_metric / extract_count_metric 的 transform,然后使用 filter 丢弃原始直方图 |
| 编辑或假名化 PII | 使用 SHA256 / replace_all_patterns 的 transform → references/redaction.md |
| 调试无数据、DNS、接收器/导出器问题或管道连接问题 | 这不是 OTTL 问题 — 请先说明这一点再继续 |
各主题的参考资料位于 references/ 下,并列在本文底部的 References 页脚中。如果问题涉及你近期未查看过的特定 processor、上下文或函数,或者用户粘贴了 Collector 错误,请先查阅相应的参考文件。针对性地阅读一两处资料,胜过凭记忆猜测。
核心概念
上下文和路径表达式
context: 决定 attributes 的含义。在 context: resource 中,attributes["k"] 是资源属性。在 context: log 或 context: span 中,attributes["k"] 是记录级属性 — 使用 resource.attributes["k"] 访问资源。上下文错误 = 静默返回 nil,不会报错。→ references/contexts.md
| 信号 | 有效上下文 |
|---|---|
| 日志 | resource、scope、log |
| trace | resource、scope、span、spanevent |
| 指标 | resource、scope、metric、datapoint |
指标级编辑(名称、描述、单位)应放在 context: metric 中;每个序列的标签/属性编辑应放在 context: datapoint 中。在同一块中混用两者,会导致其中一个静默失效。→ references/contexts.md
可以在 context: log 中通过设置 time 并使用 Time(...),或设置 time_unix_nano 并使用整数纳秒值,来更改日志事件时间戳。span 状态检查应放在 context: span 中;优先使用 STATUS_CODE_ERROR、STATUS_CODE_OK 和 STATUS_CODE_UNSET,而不是直接比较原始数值。→ references/transformations.md
错误模式
| 模式 | 行为 |
|---|---|
propagate(默认) | 任何 OTTL 运行时错误都会中止管道 — 导致数据丢失 |
ignore | 记录错误日志,跳过该语句并继续管道 — 生产环境中请使用 |
silent | 跳过该语句并抑制错误日志 |
在每个 transform 和 filter processor 上显式设置 error_mode — 默认值(propagate)会在首次运行时错误时中止整个管道(缺少可选字段、类型错误、对 nil 进行索引),并静默丢弃后续所有记录。对于“发生一次故障后管道就静默了”的问题,解决方法几乎总是补上缺失的 error_mode 键:
processors:
transform:
error_mode: ignore # log, skip the statement, continue the pipeline
log_statements:
- context: log
statements:
- set(attributes["env"], resource.attributes["deployment.environment"])
错误模式
在提出修复方案前,先将 Collector 消息对应到根本原因:
| Collector 消息 | 根本原因 | 首要操作 |
|---|---|---|
INVALID_ARGUMENT | 类型不匹配、函数输入无效,或当前上下文中的路径无效 | 添加 nil/类型保护;确认当前上下文 |
... cannot be indexed | 对非 map 值进行索引——字符串或空正文 | 在正文索引前添加 IsMap(body) 保护 |
segment "..." is not a valid path | 上下文错误,或所选上下文中不存在该字段 | 切换到正确的上下文;检查路径引用 |
one or more paths were modified to include their context prefix | 在需要显式前缀时使用了不带前缀的 attributes[...] | 改写为 resource.attributes、datapoint.attributes 等 |
statement has invalid syntax: ... invalid quoted string | YAML 与 OTTL 的引号冲突——字符串在传递给 OTTL 前已被 YAML 解析器处理 | 外层使用 YAML 单引号,内层使用 OTTL 双引号 → references/processors.md |
| 语句成功加载,但没有可见效果 | 条件始终不匹配、信号块错误,或处理器位于错误的管道阶段 | 输出调试属性以验证是否匹配;检查管道中的位置 |
标准管道结构
完整且带注释的 transform + filter 管道示例(日志/跟踪/指标语句、error_mode、conditions: [IsMap(body)]、先过滤再转换的顺序)见 references/processors.md。
常见工作流
1. 调试 OTTL 语句
- 确认问题确实出在 OTTL,而不是组件选择、管道连接或基础设施。
- 确定信号(日志/跟踪/指标)和具体上下文。
- 对照上方 错误模式 表,找到完全匹配的错误文本。
- 检查是否缺少 nil 或类型保护(
IsMap、IsString、!= nil)。 - 检查上下文前缀是否错误(
attributes与resource.attributes)。 - 检查
conditions:语义或尾部采样策略顺序。 - 只有在此之后,才提出修正后的语句和最精简的 YAML。
2. 将 JSON 日志正文提升为属性
当正文以原始 JSON 字符串形式到达时(IsMap(body) 为 false),使用
IsString(body) 进行保护,并用 ParseJSON 解析。优先使用 IsString(body),而不是
not IsMap(body)——它是肯定式检查,也能避免匹配空/nil
正文。
- context: log
conditions:
- IsString(body) # body is a JSON string (affirmative guard)
statements:
# Promote every top-level JSON field into attributes
- merge_maps(attributes, ParseJSON(body), "insert")
# Or lift specific fields only:
- set(attributes["user_id"], ParseJSON(body)["user_id"]) where ParseJSON(body)["user_id"] != nil
- set(attributes["request_id"], ParseJSON(body)["request_id"]) where ParseJSON(body)["request_id"] != nil
ParseJSON 是一个 Converter——它会返回一个值,但自身不会产生副作用,
因此必须包装在 Editor(set、merge_maps)中。单独一行
ParseJSON(body) 可以无错误地加载,但不会执行任何操作。→ references/transformations.md
3. 降低指标基数
- context: datapoint
statements:
- keep_keys(attributes, ["service.name", "http.route", "http.response.status_code"])
- delete_matching_keys(attributes, "^k8s\\.pod\\.uid$")
优先使用 keep_keys(允许列表),而不是大量调用 delete_key(阻止列表)。→ references/cardinality.md
4. 为读取资源属性的导出器提供数据
从属性中选择目标位置的导出器——尤其是 Coralogix 导出器的
application_name_attributes 和 subsystem_name_attributes——读取的是资源
属性,而不是日志记录或 span 属性。如果源值位于记录上,请从 context: log(或 context: span)中将其复制到资源:
set(resource.attributes[...], attributes[...])。不要在应用程序中重命名字段,也不要更改导出器配置。
完整模式(包括两组属性、error_mode 和管道顺序)见
→ references/contexts.md。
5. 提取直方图聚合值并丢弃源指标
为在丢弃原始桶数据的同时保留用于计算平均延迟的 _sum 和 _count:
processors:
transform:
error_mode: ignore
metric_statements:
- context: metric
conditions:
- type == METRIC_DATA_TYPE_HISTOGRAM
statements:
- extract_sum_metric(true) # creates <name>_sum as a new Sum metric; true = monotonic
- extract_count_metric(true) # creates <name>_count as a new Counter metric
filter:
error_mode: ignore
metrics:
metric:
- 'type == METRIC_DATA_TYPE_HISTOGRAM and name == "http.server.request.duration"'
extract_sum_metric(monotonic) 和 extract_count_metric(monotonic) 是 OTTL Editor 函数,在 context: metric 中运行,并将新的独立指标追加到管道输出中——原始直方图会一直保留,直到 filter 处理器将其丢弃。管道中必须先执行 transform 处理器,再执行 filter,这样新指标才会在直方图被移除之前生成。对于累积型/单调计数器,传入 true;对于增量型,传入 false。
6. 对所有属性中的 PII 脱敏
- context: log
statements:
- set(attributes["user.id"], SHA256(attributes["user.id"])) where attributes["user.id"] != nil
- replace_all_patterns(attributes, "value", "(?i)bearer\\s+[a-z0-9._-]+", "bearer ***")
SHA256 可在不暴露原始标识符的情况下保留关联性。replace_all_patterns 可对每个属性值进行脱敏,无需逐一列出键。→ references/redaction.md
最佳实践
管道与执行顺序
- 先过滤,再转换。 不要耗费 CPU 转换即将被丢弃的记录。
- 显式设置
error_mode: ignore。 默认的propagate会在任何运行时错误发生时导致数据丢失。 - 使用
conditions:限定代码块的作用范围。 任意一个列出的条件匹配时,语句就会运行(OR 语义);这比在每条语句上使用where子句开销更小。若需严格 AND,可组合使用a and b,或使用每条语句各自的where。
防御性 OTTL
- 先检查,再索引。 访问映射前使用
IsMap(body),执行字符串操作前使用IsString(body),读取可选字段前使用where attributes["x"] != nil。对错误类型进行未设防的索引操作会引发INVALID_ARGUMENT,并且(在默认的error_mode下)会中止管道。 - 比较前将看似数字的字符串转换为数值。 如果某个属性可能是
"5"或5,则使用IsString/IsInt分支,并在进行>/<比较前使用Int(...)或Double(...)。 conditions:是 OR,不是 AND。 若需严格 AND,请组合为一个布尔表达式(a and b),或为每条语句添加where。
编写风格
- 先确定信号和上下文。 将跟踪、指标和日志分开处理;使用与所引用字段相匹配的上下文。
- 优先使用多个简短语句,而不是一条复杂表达式。 在有助于清晰表达时,明确展示路径前缀。
- 优先使用
keep_keys,而不是多次调用delete_key。 允许列表更简洁,也能更清晰地说明意图。
局限性
OTTL 无法解决以下问题:接收器连接、导出器连接、DNS 或 Kubernetes 服务发现、负载均衡、网关可达性、管道接线错误,或遥测数据根本没有到达处理器。继续排查前,请先说明这一点。
范围限制:
- OTTL 只能使用当前信号和上下文模型中公开的字段。
- Collector 看到的是遥测负载,而不是原始传入请求——接收器摄取数据后,上游 HTTP 标头通常不可用。
- 如果某个字段不在当前上下文中,OTTL 就无法推断或重建该字段。
OTTL 函数列表会随每个 Collector 版本更新。本技能涵盖常见模式和误用情形;如需了解当前函数签名,请查阅下方 References 页脚中的上游文档。
参考资料
- references/contexts.md — OTTL 上下文、路径表达式以及最常见的上下文错误
- references/processors.md —
transform、filter和routing连接器配置 - references/filtering.md — 使用过滤处理器丢弃日志、指标和 Span
- references/transformations.md — Span 命名、语义约定迁移、正文操作、
ParseJSON、回退链 - references/cardinality.md — 使用
keep_keys、delete_matching_keys、replace_pattern降低指标和追踪的基数 - references/redaction.md — PII 掩码、
SHA256假名化、令牌/卡号/授权标头脱敏
上游: