otelcol.processor.transform
otelcol.processor.transform
接受来自其他 otelcol
组件的遥测数据,并使用 OpenTelemetry 转换语言 (OTTL) 对其进行修改。OTTL 语句包含 OTTL 函数,作用于路径。路径是对遥测数据的引用,例如
- 资源属性。
- 插桩范围名称。
- Span 属性。
除了 标准 OTTL 函数之外,还有一组仅用于指标的函数
- convert_sum_to_gauge
- convert_gauge_to_sum
- convert_summary_count_val_to_sum
- convert_summary_sum_val_to_sum
- copy_metric
- scale_metric
- aggregate_on_attributes
- convert_exponential_histogram_to_histogram
- aggregate_on_attribute_value
OTTL 语句还可以包含诸如以下构造
- 布尔值:
not true
not IsMatch(name, "http_.*")
- 由
where
关键字后跟一个或多个布尔值组成的布尔表达式set(attributes["whose_fault"], "ours") where attributes["http.status"] == 500
set(attributes["whose_fault"], "theirs") where attributes["http.status"] == 400 or attributes["http.status"] == 404
- 数学表达式:
1 + 1
end_time_unix_nano - start_time_unix_nano
sum([1, 2, 3, 4]) + (10 / 1) - 1
注意
在 Alloy 配置文件中有两种输入字符串的方式
- 使用引号( 普通 Alloy 语法字符串)。
\
和\"
等字符必须在其前面加上\
字符进行转义。- 使用反引号( 原始 Alloy 语法字符串)。无需转义任何字符。但是,字符串内不能包含反引号。
例如,OTTL 语句
set(description, "Sum") where type == "Sum"
可以写成
- 一个普通 Alloy 语法字符串:
"set(description, \"Sum\") where type == \"Sum\""
。- 一个原始 Alloy 语法字符串:
`set(description, "Sum") where type == "Sum"`
。原始字符串通常更方便编写 OTTL 语句。
注意
otelcol.processor.transform
是上游 OpenTelemetry Collectortransform
处理器的封装。如有必要,错误报告或功能请求将重定向到上游仓库。
您可以通过为 otelcol.processor.transform
组件赋予不同的标签来指定多个实例。
警告
otelcol.processor.transform
允许您修改遥测数据的各个方面。下面列出了一些特定的风险,但这并非完整列表。在使用此处理器之前,了解您的数据非常重要。
- 不健全的转换: 指标数据类型之间的转换未在 指标数据模型中定义。要使用这些函数,您必须了解输入数据,并知道它可以有意义地转换为新的指标数据类型,或用于创建新的指标。
- 虽然 OTTL 允许您将
set
函数与metric.data_type
一起使用,但其在转换处理器中的实现是一个 空操作。要修改数据类型,您必须使用特定的函数,例如convert_gauge_to_sum
。- 身份冲突: 指标转换可能会影响指标的身份,导致身份危机。转换指标名称以及减少或更改现有属性时要特别谨慎。添加新属性是安全的。
- 孤立遥测: 该处理器允许您修改追踪数据的
span_id
、trace_id
和parent_span_id
,以及日志数据的span_id
和trace_id
。修改这些字段可能导致孤立的 span 或日志。
用法
otelcol.processor.transform "LABEL" {
output {
metrics = [...]
logs = [...]
traces = [...]
}
}
参数
otelcol.processor.transform
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
error_mode | string | 在处理语句时如果发生错误如何响应。 | "propagate" | 否 |
error_mode
支持的值为
ignore
: 忽略条件返回的错误,记录它们并继续处理下一个条件。这是推荐的模式。silent
: 忽略条件返回的错误,不记录它们并继续处理下一个条件。propagate
: 将错误返回到 Pipeline 上层。这将导致负载从 Alloy 中丢弃。
块
otelcol.processor.transform
的定义中支持以下块
层级 | 块 | 描述 | 必需 |
---|---|---|---|
trace_statements | trace_statements | 转换追踪的语句。 | 否 |
metric_statements | metric_statements | 转换指标的语句。 | 否 |
log_statements | log_statements | 转换日志的语句。 | 否 |
statements | [statements][] | 转换日志、指标和追踪的语句,无需显式指定上下文。 | 否 |
output | output | 配置将接收到的遥测数据发送到何处。 | 是 |
debug_metrics | debug_metrics | 配置此组件生成的用于监控自身状态的指标。 | 否 |
trace_statements 块
trace_statements
块指定了用于转换追踪遥测信号的语句。可以指定多个 trace_statements
块。
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
context | string | 解释关联语句时使用的 OTTL 上下文。 | 是 | |
statements | list(string) | OTTL 语句列表。 | 是 |
context
支持的值为
resource
: 仅与 OTLP 资源交互时使用(例如,资源属性)。scope
: 仅与 OTLP 插桩范围交互时使用(例如,插桩范围的名称)。span
: 仅与 OTLP span 交互时使用。spanevent
: 仅与 OTLP span 事件交互时使用。
请参考OTTL Context了解如何使用上下文的更多信息。
metric_statements 块
metric_statements
块指定了用于转换指标遥测信号的语句。可以指定多个 metric_statements
块。
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
context | string | 解释关联语句时使用的 OTTL 上下文。 | 是 | |
statements | list(string) | OTTL 语句列表。 | 是 |
context
支持的值为
resource
: 仅与 OTLP 资源交互时使用(例如,资源属性)。scope
: 仅与 OTLP 插桩范围交互时使用(例如,插桩范围的名称)。metric
: 仅与单个 OTLP 指标交互时使用。datapoint
: 仅与单个 OTLP 指标数据点交互时使用。
请参考OTTL Context了解如何使用上下文的更多信息。
log_statements 块
log_statements
块指定了用于转换日志遥测信号的语句。可以指定多个 log_statements
块。
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
context | string | 解释关联语句时使用的 OTTL 上下文。 | 是 | |
statements | list(string) | OTTL 语句列表。 | 是 |
context
支持的值为
resource
: 仅与 OTLP 资源交互时使用(例如,资源属性)。scope
: 仅与 OTLP 插桩范围交互时使用(例如,插桩范围的名称)。log
: 仅与 OTLP 日志交互时使用。
请参考OTTL Context了解如何使用上下文的更多信息。
statements 块
statements
块指定了用于转换日志、指标或追踪遥测信号的语句。没有 context
配置参数 - 上下文将从语句中推断。这种推断基于语句中存在的路径名称、函数和枚举。至少一个上下文必须能够解析所有语句。
statements
块可以替代 log_statements
、metric_statements
和 trace_statements
块。它也可以与它们一起使用。
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
log | list(string) | 转换日志的 OTTL 语句列表。 | [] | 否 |
metric | list(string) | 转换指标的 OTTL 语句列表。 | [] | 否 |
trace | list(string) | 转换追踪的 OTTL 语句列表。 | [] | 否 |
推断是自动发生的,因为路径名称前缀带有上下文名称。在以下示例中,推断的上下文值为 datapoint
,因为它是唯一支持解析数据点和指标路径的上下文
statements {
metric = [`set(metric.description, "test passed") where datapoint.attributes["test"] == "pass"`]
}
在以下示例中,推断的上下文是 metric
,因为 metric
是能够解析指标和资源数据的上下文
statements {
metric = [
`resource.attributes["test"], "passed"`,
`set(metric.description, "test passed"`,
]
}
上下文推断的主要好处在于,它通过将语句链接到最合适的上下文来提高语句处理效率。这种优化确保数据转换既准确又高效,利用上下文的层次结构避免不必要的迭代并提高整体处理效率。所有这些都是自动发生的,您可以编写 OTTL 语句而无需担心上下文。
OTTL 上下文
每个上下文都允许转换其类型的遥测数据。例如,与 resource
上下文相关的语句将能够转换资源的 attributes
和 dropped_attributes_count
。
每种类型的 context
都定义了特定于该上下文的路径和枚举。请参考 OpenTelemetry 文档了解每种上下文的路径和枚举列表
上下文绝不提供对 protobuf 定义中“较低”的单个项的访问权限。
- 这意味着与
resource
关联的语句无法访问底层的插桩范围。 - 这意味着与
scope
关联的语句无法访问底层的遥测切片(span、指标或日志)。 - 类似地,与
metric
关联的语句无法访问单个数据点,但可以访问整个数据点切片。 - 类似地,与
span
关联的语句无法访问单个 SpanEvent,但可以访问整个 SpanEvent 切片。
出于实际目的,这意味着上下文不能根据结构中“较低”的遥测数据来决定其自身的遥测数据。例如,以下上下文语句是不可能的,因为它试图在与 metric
关联的语句的条件中使用单个数据点属性
metric_statements {
context = "metric"
statements = [
"set(description, \"test passed\") where datapoints.attributes[\"test\"] == \"pass\"",
]
}
上下文总是提供对 protobuf 定义中“较高”的与正在转换的遥测数据关联的项的访问权限。
- 这意味着与
datapoint
关联的语句可以访问数据点的指标、插桩范围和资源。 - 这意味着与
spanevent
关联的语句可以访问 spanevent 的 span、插桩范围和资源。 - 这意味着与
span
/metric
/log
关联的语句可以访问遥测数据的插桩范围和资源。 - 这意味着与
scope
关联的语句可以访问范围的资源。
例如,以下上下文语句是可能的,因为 datapoint
语句可以访问数据点的指标。
metric_statements {
context = "datapoint"
statements = [
"set(metric.description, \"test passed\") where attributes[\"test\"] == \"pass\"",
]
}
OTLP 信号的 protobuf 定义在 GitHub 上维护
尽可能地将您的语句与语句旨在转换的上下文关联。上下文是嵌套的,较高级别的上下文无需迭代较低级别的任何上下文。例如,虽然您可以使用 span
上下文修改与 span 关联的资源属性,但使用 resource
上下文更高效。
output 块
output
块配置一组组件用于转发生成的遥测数据。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
logs | list(otelcol.Consumer) | 要发送日志到的消费者列表。 | [] | 否 |
metrics | list(otelcol.Consumer) | 要发送指标到的消费者列表。 | [] | 否 |
traces | list(otelcol.Consumer) | 要发送追踪到的消费者列表。 | [] | 否 |
您必须指定 output
块,但其所有参数都是可选的。默认情况下,遥测数据会被丢弃。相应地配置 metrics
、logs
和 traces
参数,以将遥测数据发送到其他组件。
debug_metrics 块
debug_metrics
块配置此组件生成的用于监控其状态的指标。
支持以下参数
名称 | 类型 | 描述 | 默认值 | 必需 |
---|---|---|---|---|
disable_high_cardinality_metrics | 布尔值 | 是否禁用某些高基数指标。 | true | 否 |
disable_high_cardinality_metrics
是 Grafana Alloy 中等同于 OpenTelemetry Collector 中的 telemetry.disableHighCardinalityMetrics
功能门。它会移除可能导致高基数指标的属性。例如,Metrics 中关于 HTTP 和 gRPC 连接的带有 IP 地址和端口号的属性将被移除。
注意
如果配置,
disable_high_cardinality_metrics
仅适用于otelcol.exporter.*
和otelcol.receiver.*
组件。
导出字段
以下字段被导出,可供其他组件引用
名称 | 类型 | 描述 |
---|---|---|
input | otelcol.Consumer | 其他组件可以用来发送遥测数据的值。 |
input
接受用于任何遥测信号(指标、日志或追踪)的 otelcol.Consumer
数据。
组件健康状况
仅当配置无效时,otelcol.processor.transform
才会被报告为不健康。
调试信息
otelcol.processor.transform
不公开任何组件特定的调试信息。
调试指标
otelcol.processor.transform
不公开任何组件特定的调试指标。
示例
如果属性不存在则执行转换
此示例在属性 test
不存在时将其值设置为 pass
。
otelcol.processor.transform "default" {
error_mode = "ignore"
trace_statements {
context = "span"
statements = [
// Accessing a map with a key that does not exist will return nil.
`set(attributes["test"], "pass") where attributes["test"] == nil`,
]
}
output {
metrics = [otelcol.exporter.otlp.default.input]
logs = [otelcol.exporter.otlp.default.input]
traces = [otelcol.exporter.otlp.default.input]
}
}
重命名资源属性
有两种方法可以重命名属性键。一种方法是设置一个新的属性并删除旧的属性
otelcol.processor.transform "default" {
error_mode = "ignore"
trace_statements {
context = "resource"
statements = [
`set(attributes["namespace"], attributes["k8s.namespace.name"])`,
`delete_key(attributes, "k8s.namespace.name")`,
]
}
output {
metrics = [otelcol.exporter.otlp.default.input]
logs = [otelcol.exporter.otlp.default.input]
traces = [otelcol.exporter.otlp.default.input]
}
}
另一种方法是使用正则表达式更新键
otelcol.processor.transform "default" {
error_mode = "ignore"
trace_statements {
context = "resource"
statements = [
`replace_all_patterns(attributes, "key", "k8s\\.namespace\\.name", "namespace")`,
]
}
output {
metrics = [otelcol.exporter.otlp.default.input]
logs = [otelcol.exporter.otlp.default.input]
traces = [otelcol.exporter.otlp.default.input]
}
}
从日志正文内容创建属性
此示例将属性 body
设置为日志正文的值
otelcol.processor.transform "default" {
error_mode = "ignore"
log_statements {
context = "log"
statements = [
`set(attributes["body"], body)`,
]
}
output {
metrics = [otelcol.exporter.otlp.default.input]
logs = [otelcol.exporter.otlp.default.input]
traces = [otelcol.exporter.otlp.default.input]
}
}
组合两个属性
此示例将属性 test
设置为属性 service.name
和 service.version
组合后的值。
otelcol.processor.transform "default" {
error_mode = "ignore"
trace_statements {
context = "resource"
statements = [
// The Concat function combines any number of strings, separated by a delimiter.
`set(attributes["test"], Concat([attributes["service.name"], attributes["service.version"]], " "))`,
]
}
output {
metrics = [otelcol.exporter.otlp.default.input]
logs = [otelcol.exporter.otlp.default.input]
traces = [otelcol.exporter.otlp.default.input]
}
}
解析 JSON 日志
给定以下 JSON 正文
{
"name": "log",
"attr1": "example value 1",
"attr2": "example value 2",
"nested": {
"attr3": "example value 3"
}
}
您可以将特定字段作为日志属性添加
otelcol.processor.transform "default" {
error_mode = "ignore"
log_statements {
context = "log"
statements = [
// Parse body as JSON and merge the resulting map with the cache map, ignoring non-json bodies.
// cache is a field exposed by OTTL that is a temporary storage place for complex operations.
`merge_maps(cache, ParseJSON(body), "upsert") where IsMatch(body, "^\\{")`,
// Set attributes using the values merged into cache.
// If the attribute doesn't exist in cache then nothing happens.
`set(attributes["attr1"], cache["attr1"])`,
`set(attributes["attr2"], cache["attr2"])`,
// To access nested maps you can chain index ([]) operations.
// If nested or attr3 do no exist in cache then nothing happens.
`set(attributes["nested.attr3"], cache["nested"]["attr3"])`,
]
}
output {
metrics = [otelcol.exporter.otlp.default.input]
logs = [otelcol.exporter.otlp.default.input]
traces = [otelcol.exporter.otlp.default.input]
}
}
属性和状态码的各种转换
该示例通过将转换与 intended 转换的上下文进行分组来利用上下文效率。
otelcol.receiver.otlp "default" {
http {}
grpc {}
output {
metrics = [otelcol.processor.transform.default.input]
logs = [otelcol.processor.transform.default.input]
traces = [otelcol.processor.transform.default.input]
}
}
otelcol.processor.transform "default" {
error_mode = "ignore"
trace_statements {
context = "resource"
statements = [
`keep_keys(attributes, ["service.name", "service.namespace", "cloud.region", "process.command_line"])`,
`replace_pattern(attributes["process.command_line"], "password\\=[^\\s]*(\\s?)", "password=***")`,
`limit(attributes, 100, [])`,
`truncate_all(attributes, 4096)`,
]
}
trace_statements {
context = "span"
statements = [
`set(status.code, 1) where attributes["http.path"] == "/health"`,
`set(name, attributes["http.route"])`,
`replace_match(attributes["http.target"], "/user/*/list/*", "/user/{userId}/list/{listId}")`,
`limit(attributes, 100, [])`,
`truncate_all(attributes, 4096)`,
]
}
metric_statements {
context = "resource"
statements = [
`keep_keys(attributes, ["host.name"])`,
`truncate_all(attributes, 4096)`,
]
}
metric_statements {
context = "metric"
statements = [
`set(description, "Sum") where type == "Sum"`,
`convert_sum_to_gauge() where name == "system.processes.count"`,
`convert_gauge_to_sum("cumulative", false) where name == "prometheus_metric"`,
`aggregate_on_attributes("sum") where name == "system.memory.usage"`,
]
}
metric_statements {
context = "datapoint"
statements = [
`limit(attributes, 100, ["host.name"])`,
`truncate_all(attributes, 4096)`,
]
}
log_statements {
context = "resource"
statements = [
`keep_keys(attributes, ["service.name", "service.namespace", "cloud.region"])`,
]
}
log_statements {
context = "log"
statements = [
`set(severity_text, "FAIL") where body == "request failed"`,
`replace_all_matches(attributes, "/user/*/list/*", "/user/{userId}/list/{listId}")`,
`replace_all_patterns(attributes, "value", "/account/\\d{4}", "/account/{accountId}")`,
`set(body, attributes["http.route"])`,
]
}
output {
metrics = [otelcol.exporter.otlp.default.input]
logs = [otelcol.exporter.otlp.default.input]
traces = [otelcol.exporter.otlp.default.input]
}
}
otelcol.exporter.otlp "default" {
client {
endpoint = sys.env("OTLP_ENDPOINT")
}
}
兼容组件
otelcol.processor.transform
可以接受来自以下组件的参数
otelcol.processor.transform
具有可供以下组件消费的导出
注意
连接某些组件可能不合理,或者组件可能需要进一步配置才能使连接正常工作。请参考链接文档了解更多详情。