如何用 OTel Collector 的 transform 与 filter 处理器在导出前规范化并过滤日志?
2026/9/9 23:17:58 网站建设 项目流程

如何用 OTel Collector 的 transform 与 filter 处理器在导出前规范化并过滤日志?

【免费下载链接】netdataThe fastest path to AI-powered full stack observability, even for lean teams.项目地址: https://gitcode.com/GitHub_Trending/ne/netdata

当多个 receiver 采集到的日志在发送到 Netdata 之前需要统一做同样的事——把 JSON 日志体展开成属性、把应用自有的level字段提升为 severity、补上缺失的 service 标识,再丢掉健康检查之类的噪声记录——OTel Collector 的transformfilter处理器就是干这个的。本文适用于已经跑通 Ingest OpenTelemetry Metrics and Logs 中前置步骤的环境:本机有一个带 OpenTelemetry 插件的 Netdata Agent,Collector 与 Agent 同主机,通过127.0.0.1:4317的 OTLP/gRPC 端点通信。文档示例均使用 OpenTelemetry Collector Contrib0.157.0验证。

前提:先确认采集链路已通

在写处理器之前,先保证最小链路能工作。要点(来自 Ingest OpenTelemetry Metrics and Logs):

  • Netdata Agent 必须带 OpenTelemetry 插件。Linux 原生 DEB/RPM 包作为netdata的依赖安装,静态构建默认捆绑(32 位 ARMv6 除外),所有 Docker 镜像都包含;Linux 源码构建需要--enable-plugin-otel。插件在 Windows 和 FreeBSD 上不可用。
  • 导出端只能用otlp_grpcexporter 加端口4317。Netdata 不接受otlp_httpexporter 或 OTLP/HTTP 端口4318;如果localhost解析到 IPv6,请写127.0.0.1
  • 同主机回环连接可以用下面这个禁用 TLS 的 exporter,跨主机时要改用 TLS,详见 Securing the OTLP Endpoint:
exporters: otlp_grpc/netdata: endpoint: "127.0.0.1:4317" tls: insecure: true

验证otel-logs视图需要 Netdata Cloud 账号并登录,该视图是有访问门槛的。

何时用 transform,而不是 receiver 自带的解析器

如果某类格式只在某一个文件源出现,优先用 receiver 内置的解析能力。file_logreceiver 的operators可以直接加json_parser,在采集时就把时间戳和 severity 提升为 OpenTelemetry 日志记录字段:

receivers: file_log/my_application: include: [/var/log/myapp/*.json] start_at: end operators: - type: json_parser timestamp: parse_from: attributes.time layout: "%Y-%m-%dT%H:%M:%S.%LZ" severity: parse_from: attributes.level

transform处理器适合跨多个 receiver 复用、或需要在采集之后统一改写的场景;filter处理器则专门用来丢弃记录。下面的所有配置均假定你在一条共享的 logs 管道上做这种统一处理。

用 transform 解析 JSON 日志体

当日志的 body 是一段 JSON 字符串时,用ParseJSON解析并把键合并进日志属性:

processors: transform/parse_json: error_mode: ignore log_statements: - 'merge_maps(log.attributes, ParseJSON(log.body), "insert") where IsString(log.body)'

对于形如{"level":"error","msg":"connection refused","duration_ms":312}的 body,处理器会添加levelmsgduration_ms三个属性,同时保留原始 body。insert策略在已存在同名属性时保留原值;error_mode: ignore让非法 JSON 的记录继续走管道,Collector 只记录转换错误。where IsString(log.body)保证只对字符串 body 执行。注意ParseJSON要求 body 是 JSON 字符串,遇到非字符串或非法 JSON 会返回错误。

用 transform 规范化 severity 与资源标识

解析出level之后,把它提升为 severity text,并在缺失时补上 Netdata Logs tab 用来识别流的 resource 标识:

processors: transform/normalize_logs: error_mode: ignore log_statements: - 'set(log.severity_text, log.attributes["level"]) where log.attributes["level"] != nil' - 'set(resource.attributes["service.name"], "my-application") where resource.attributes["service.name"] == nil' - 'set(resource.attributes["service.namespace"], "production") where resource.attributes["service.namespace"] == nil'

第一条语句只把源值原样保存为文本,它不会推断出 OpenTelemetry 的 severity number。如果下游条件或仪表盘依赖数值 severity,需要按来源的级别显式映射,不要假设所有应用使用同一套标尺。

静态的service.name/service.namespace只在管道只服务一个已知服务时合适;共享管道应从可信的 receiver 元数据派生标识,或保留应用已有的 OpenTelemetry resource 属性。

用 filter 丢弃噪声记录

注意:transform里给属性赋值不会丢弃记录,丢记录必须用filter处理器的log_conditions——任意一条条件命中,该记录即被丢弃(条件之间是 OR 关系):

processors: filter/drop_noise: error_mode: ignore log_conditions: - 'IsMatch(log.body, "(?i)health.?check")'

filter 的位置很关键:放在 Netdata exporter 之前,也放在任何不应统计被丢弃记录的 connector 之前。filter 会永久丢弃匹配的遥测数据,文档建议从窄条件开始、先观察代表性输入、在非关键管道上测试,再部署。

组装一条完整的文件到 Netdata 管道

把上面的组件拼起来:tail 一份 JSON 行日志,解析 body,缺失时补 service 标识,丢弃健康检查,再把剩余日志发到本机 Netdata Agent:

receivers: file_log/my_application: include: [/var/log/myapp/*.json] start_at: end processors: transform/prepare_logs: error_mode: ignore log_statements: - 'merge_maps(log.attributes, ParseJSON(log.body), "insert") where IsString(log.body)' - 'set(log.severity_text, log.attributes["level"]) where log.attributes["level"] != nil' - 'set(resource.attributes["service.name"], "my-application") where resource.attributes["service.name"] == nil' filter/drop_health_checks: error_mode: ignore log_conditions: - 'IsMatch(log.body, "(?i)health.?check")' exporters: otlp_grpc/netdata: endpoint: "127.0.0.1:4317" tls: insecure: true service: pipelines: logs: receivers: [file_log/my_application] processors: [transform/prepare_logs, filter/drop_health_checks] exporters: [otlp_grpc/netdata]

处理器顺序是这条管道能不能生效的核心,遵循文档给出的 OTTL 操作规则:

  • 用信号专属路径写语句和条件,如log.bodylog.attributesresource.attributes
  • where让单条语句有条件地执行;filter 条件不同,任一命中即丢弃。
  • 先解析、再读取解析出的属性;先规范化、再按规范化后的值过滤;过滤放在不应收到被丢弃记录的 connector 和 exporter 之前。
  • error_mode: ignore会记录求值错误并继续处理;只有当你宁可丢弃受影响的载荷也不转发未转换数据时,才用propagate
  • OTTL 语法和处理器配置随版本演进,以你所部署的确切 Collector 版本的上游文档为准。

生产环境的文件采集还应加上持久化 offset(file_storage扩展 + receiver 的storage选项),做法见 Collect Logs with OpenTelemetry Collector 的 Application log files 一节;不带 storage 时 offset 只存在内存里,重启行为取决于start_at

验证结果

  1. 保存配置后按你的安装方式启动或重载 Collector。
  2. 在 Netdata 打开该节点的Logstab,选择otel-logs数据源,再用Services选择器选中你配置的服务。Netdata 里存储的服务字段就是resource.attributes.service.name,所以第 4 节 transform 中补的service.name直接决定这里能选中什么。
  3. 如果 Collector 报告导出成功但记录缺失,检查记录的时间戳:Netdata 只接受过去 24 小时内、未来 10 分钟内的记录,被拒的记录通过 OTLPpartial_success上报。

排查与边界

文档给出的对照项如下,出现对应现象时按此判断:

  • Collector 拒绝配置:用你确切在用的 Collector 版本核对组件标识符和 OTTL 路径。transformfilter是 Contrib 组件,Core 发行版里不一定有。
  • 解析出的属性没有出现:用临时的 debug exporter 检查 incoming body 的类型和值。ParseJSON要求 JSON 字符串,非法 JSON 会返回错误(在error_mode: ignore下记录会继续走管道)。
  • severity 过滤表现异常:先确认来源到底设置了severity_number、只有severity_text、还是自定义属性。文本到数值的映射需要按来源单独写规则。
  • 太多记录消失了:移除或收窄 filter 条件,同时观察代表性记录。log_conditions内的条件按 OR 组合。
  • Netdata 收到了日志但 service 选择器是空的:在导出前设置resource.attributes.service.name,然后在otel-logs数据源里核对它。

最后一条容易踩的边界:transform 和 filter 只待在一条信号管道内,它们不会把日志变成指标。如果你要从匹配的日志记录派生指标(例如 warning/error 计数),需要 connector 桥接 logs 和 metrics 管道,Netdata 维护的配方在 Create metrics from OpenTelemetry logs。

【免费下载链接】netdataThe fastest path to AI-powered full stack observability, even for lean teams.项目地址: https://gitcode.com/GitHub_Trending/ne/netdata

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询