菜单
文档breadcrumb arrow Grafana Alloybreadcrumb arrow 参考breadcrumb arrow 组件breadcrumb arrow otelcolbreadcrumb arrow otelcol.processor.transform
开源

otelcol.processor.transform

otelcol.processor.transform 接受来自其他 otelcol 组件的遥测数据,并使用 OpenTelemetry 转换语言 (OTTL) 对其进行修改。OTTL 语句包含 OTTL 函数,作用于路径。路径是对遥测数据的引用,例如

  • 资源属性。
  • 插桩范围名称。
  • Span 属性。

除了 标准 OTTL 函数之外,还有一组仅用于指标的函数

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 配置文件中有两种输入字符串的方式

例如,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 Collector transform 处理器的封装。如有必要,错误报告或功能请求将重定向到上游仓库。

您可以通过为 otelcol.processor.transform 组件赋予不同的标签来指定多个实例。

警告

otelcol.processor.transform 允许您修改遥测数据的各个方面。下面列出了一些特定的风险,但这并非完整列表。在使用此处理器之前,了解您的数据非常重要。

  • 不健全的转换: 指标数据类型之间的转换未在 指标数据模型中定义。要使用这些函数,您必须了解输入数据,并知道它可以有意义地转换为新的指标数据类型,或用于创建新的指标。
    • 虽然 OTTL 允许您将 set 函数与 metric.data_type 一起使用,但其在转换处理器中的实现是一个 空操作。要修改数据类型,您必须使用特定的函数,例如 convert_gauge_to_sum
  • 身份冲突: 指标转换可能会影响指标的身份,导致身份危机。转换指标名称以及减少或更改现有属性时要特别谨慎。添加新属性是安全的。
  • 孤立遥测: 该处理器允许您修改追踪数据的 span_idtrace_idparent_span_id,以及日志数据的 span_idtrace_id。修改这些字段可能导致孤立的 span 或日志。

用法

alloy
otelcol.processor.transform "LABEL" {
  output {
    metrics = [...]
    logs    = [...]
    traces  = [...]
  }
}

参数

otelcol.processor.transform 支持以下参数

名称类型描述默认值必需
error_modestring在处理语句时如果发生错误如何响应。"propagate"

error_mode 支持的值为

  • ignore: 忽略条件返回的错误,记录它们并继续处理下一个条件。这是推荐的模式。
  • silent: 忽略条件返回的错误,不记录它们并继续处理下一个条件。
  • propagate: 将错误返回到 Pipeline 上层。这将导致负载从 Alloy 中丢弃。

otelcol.processor.transform 的定义中支持以下块

层级描述必需
trace_statementstrace_statements转换追踪的语句。
metric_statementsmetric_statements转换指标的语句。
log_statementslog_statements转换日志的语句。
statements[statements][]转换日志、指标和追踪的语句,无需显式指定上下文。
outputoutput配置将接收到的遥测数据发送到何处。
debug_metricsdebug_metrics配置此组件生成的用于监控自身状态的指标。

trace_statements 块

trace_statements 块指定了用于转换追踪遥测信号的语句。可以指定多个 trace_statements 块。

名称类型描述默认值必需
contextstring解释关联语句时使用的 OTTL 上下文。
statementslist(string)OTTL 语句列表。

context 支持的值为

  • resource: 仅与 OTLP 资源交互时使用(例如,资源属性)。
  • scope: 仅与 OTLP 插桩范围交互时使用(例如,插桩范围的名称)。
  • span: 仅与 OTLP span 交互时使用。
  • spanevent: 仅与 OTLP span 事件交互时使用。

请参考OTTL Context了解如何使用上下文的更多信息。

metric_statements 块

metric_statements 块指定了用于转换指标遥测信号的语句。可以指定多个 metric_statements 块。

名称类型描述默认值必需
contextstring解释关联语句时使用的 OTTL 上下文。
statementslist(string)OTTL 语句列表。

context 支持的值为

  • resource: 仅与 OTLP 资源交互时使用(例如,资源属性)。
  • scope: 仅与 OTLP 插桩范围交互时使用(例如,插桩范围的名称)。
  • metric: 仅与单个 OTLP 指标交互时使用。
  • datapoint: 仅与单个 OTLP 指标数据点交互时使用。

请参考OTTL Context了解如何使用上下文的更多信息。

log_statements 块

log_statements 块指定了用于转换日志遥测信号的语句。可以指定多个 log_statements 块。

名称类型描述默认值必需
contextstring解释关联语句时使用的 OTTL 上下文。
statementslist(string)OTTL 语句列表。

context 支持的值为

  • resource: 仅与 OTLP 资源交互时使用(例如,资源属性)。
  • scope: 仅与 OTLP 插桩范围交互时使用(例如,插桩范围的名称)。
  • log: 仅与 OTLP 日志交互时使用。

请参考OTTL Context了解如何使用上下文的更多信息。

statements 块

statements 块指定了用于转换日志、指标或追踪遥测信号的语句。没有 context 配置参数 - 上下文将从语句中推断。这种推断基于语句中存在的路径名称、函数和枚举。至少一个上下文必须能够解析所有语句。

statements 块可以替代 log_statementsmetric_statementstrace_statements 块。它也可以与它们一起使用。

名称类型描述默认值必需
loglist(string)转换日志的 OTTL 语句列表。[]
metriclist(string)转换指标的 OTTL 语句列表。[]
tracelist(string)转换追踪的 OTTL 语句列表。[]

推断是自动发生的,因为路径名称前缀带有上下文名称。在以下示例中,推断的上下文值为 datapoint,因为它是唯一支持解析数据点和指标路径的上下文

alloy
statements {
    metric = [`set(metric.description, "test passed") where datapoint.attributes["test"] == "pass"`]
}

在以下示例中,推断的上下文是 metric,因为 metric 是能够解析指标和资源数据的上下文

alloy
statements {
    metric = [
        `resource.attributes["test"], "passed"`,
        `set(metric.description, "test passed"`,
    ]
}

上下文推断的主要好处在于,它通过将语句链接到最合适的上下文来提高语句处理效率。这种优化确保数据转换既准确又高效,利用上下文的层次结构避免不必要的迭代并提高整体处理效率。所有这些都是自动发生的,您可以编写 OTTL 语句而无需担心上下文。

OTTL 上下文

每个上下文都允许转换其类型的遥测数据。例如,与 resource 上下文相关的语句将能够转换资源的 attributesdropped_attributes_count

每种类型的 context 都定义了特定于该上下文的路径和枚举。请参考 OpenTelemetry 文档了解每种上下文的路径和枚举列表

上下文绝不提供对 protobuf 定义中“较低”的单个项的访问权限。

  • 这意味着与 resource 关联的语句无法访问底层的插桩范围。
  • 这意味着与 scope 关联的语句无法访问底层的遥测切片(span、指标或日志)。
  • 类似地,与 metric 关联的语句无法访问单个数据点,但可以访问整个数据点切片。
  • 类似地,与 span 关联的语句无法访问单个 SpanEvent,但可以访问整个 SpanEvent 切片。

出于实际目的,这意味着上下文不能根据结构中“较低”的遥测数据来决定其自身的遥测数据。例如,以下上下文语句是不可能的,因为它试图在与 metric 关联的语句的条件中使用单个数据点属性

alloy
metric_statements {
  context = "metric"
  statements = [
    "set(description, \"test passed\") where datapoints.attributes[\"test\"] == \"pass\"",
  ]
}

上下文总是提供对 protobuf 定义中“较高”的与正在转换的遥测数据关联的项的访问权限。

  • 这意味着与 datapoint 关联的语句可以访问数据点的指标、插桩范围和资源。
  • 这意味着与 spanevent 关联的语句可以访问 spanevent 的 span、插桩范围和资源。
  • 这意味着与 span/metric/log 关联的语句可以访问遥测数据的插桩范围和资源。
  • 这意味着与 scope 关联的语句可以访问范围的资源。

例如,以下上下文语句是可能的,因为 datapoint 语句可以访问数据点的指标。

alloy
metric_statements {
  context = "datapoint"
  statements = [
    "set(metric.description, \"test passed\") where attributes[\"test\"] == \"pass\"",
  ]
}

OTLP 信号的 protobuf 定义在 GitHub 上维护

尽可能地将您的语句与语句旨在转换的上下文关联。上下文是嵌套的,较高级别的上下文无需迭代较低级别的任何上下文。例如,虽然您可以使用 span 上下文修改与 span 关联的资源属性,但使用 resource 上下文更高效。

output 块

output 块配置一组组件用于转发生成的遥测数据。

支持以下参数

名称类型描述默认值必需
logslist(otelcol.Consumer)要发送日志到的消费者列表。[]
metricslist(otelcol.Consumer)要发送指标到的消费者列表。[]
traceslist(otelcol.Consumer)要发送追踪到的消费者列表。[]

您必须指定 output 块,但其所有参数都是可选的。默认情况下,遥测数据会被丢弃。相应地配置 metricslogstraces 参数,以将遥测数据发送到其他组件。

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.* 组件。

导出字段

以下字段被导出,可供其他组件引用

名称类型描述
inputotelcol.Consumer其他组件可以用来发送遥测数据的值。

input 接受用于任何遥测信号(指标、日志或追踪)的 otelcol.Consumer 数据。

组件健康状况

仅当配置无效时,otelcol.processor.transform 才会被报告为不健康。

调试信息

otelcol.processor.transform 不公开任何组件特定的调试信息。

调试指标

otelcol.processor.transform 不公开任何组件特定的调试指标。

示例

如果属性不存在则执行转换

此示例在属性 test 不存在时将其值设置为 pass

alloy
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]
  }
}

重命名资源属性

有两种方法可以重命名属性键。一种方法是设置一个新的属性并删除旧的属性

alloy
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]
  }
}

另一种方法是使用正则表达式更新键

alloy
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 设置为日志正文的值

alloy
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.nameservice.version 组合后的值。

alloy
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 正文

json
{
  "name": "log",
  "attr1": "example value 1",
  "attr2": "example value 2",
  "nested": {
    "attr3": "example value 3"
  }
}

您可以将特定字段作为日志属性添加

alloy
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 转换的上下文进行分组来利用上下文效率。

alloy
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 具有可供以下组件消费的导出

注意

连接某些组件可能不合理,或者组件可能需要进一步配置才能使连接正常工作。请参考链接文档了解更多详情。