Telegraf Regex 处理器完整指南:用正则批量转换与重命名指标数据
【免费下载链接】telegrafAgent for collecting, processing, aggregating, and writing metrics, logs, and other arbitrary data.项目地址: https://gitcode.com/GitHub_Trending/te/telegraf
Telegraf 的regex处理器(processor)允许你使用正则表达式对指标的 tag 值、field 值以及 tag 名、field 名、指标名(measurement)进行转换与重命名,支持捕获组、命名组和批量处理。本文以仓库中 plugins/processors/regex/README.md 为主线,结合 regex.go 与 converter.go 的源码实现与 regex_test.go 的测试用例,完整讲解该处理器的配置参数、工作原理与实战用法,读完后你可以直接在 Telegraf 管线中落地基于正则的数据清洗、脱敏和字段重组。
一、功能概述与适用场景
regex处理器是一个通用的数据转换插件,核心能力可概括为四类:
- tag 值 / field 值转换:按正则匹配值并用替换表达式改写,也支持通过命名组一次批量生成多个新 tag / field;
- tag 重命名 / field 重命名:基于正则匹配 tag 名 / field 名,将其重命名为新名称;
- 指标名(measurement)重命名:基于正则匹配指标名并重命名。
它最典型的应用场景包括:把resp_code=200归一化为resp_code=2xx以方便聚合、从request="/api/search/..."这类 URL 字段中抽取method、category等子维度、去掉字段名上的前缀(如client_ip→ip)、以及把nginx_requests这类带后缀的指标名收敛为nginx。
该插件在仓库中注册名称为regex(见 regex.go 中的processors.Add("regex", ...)),自 Telegraf v1.7.0 起引入,类型标注为 transformation,适用于所有平台。
⚠️重要限制:
regex处理器只对字符串类型的 field 生效。整数、浮点数、布尔值等其他数据类型的 field 会被直接跳过(详见下文源码分析)。
二、全局配置选项
与所有 Telegraf 插件一样,regex处理器也支持各类全局配置设置,用于修饰指标、tag、field、创建别名(alias)以及配置插件执行顺序。这些内容统一收录在 docs/CONFIGURATION.md#plugins 中,包括但不限于:
- 指标过滤类:
namepass、namedrop、pass、drop、tagpass、tagdrop、tagexclude、taginclude、fieldpass、fielddrop等; namepass_separator等参数,用于配置过滤表达式的分隔符;alias与order等处理器通用设置。
在本文所有示例中出现的namepass = ["nginx_requests"]就属于这类全局配置,其作用是只让指标名为nginx_requests的指标进入处理器,避免影响其他指标。
三、配置参数详解
一份完整的示例配置见 sample.conf,它同时也是插件通过go:embed内置的默认示例(见 regex.go)。regex处理器由五类可重复的配置小节组成,它们可以同时配置多个,且全部会被依次应用:
# Transforms tag and field values as well as measurement, tag and field names with regex pattern [[processors.regex]] namepass = ["nginx_requests"] ## Tag value conversion(s). Multiple instances are allowed. [[processors.regex.tags]] ## Tag(s) to process with optional glob expressions such as '*'. key = "resp_code" ## Regular expression to match the tag value. If the value doesn't ## match the tag is ignored. pattern = "^(\\d)\\d\\d$" ## Replacement expression defining the value of the target tag. You can ## use regexp groups or named groups e.g. ${1} references the first group. replacement = "${1}xx" ## Name of the target tag defaulting to 'key' if not specified. ## In case of wildcards being used in `key` the currently processed ## tag-name is used as target. # result_key = "method" ## Appends the replacement to the target tag instead of overwriting it when ## set to true. # append = false ## Field value conversion(s). Multiple instances are allowed. [[processors.regex.fields]] ## Field(s) to process with optional glob expressions such as '*'. key = "request" ## Regular expression to match the field value. If the value doesn't ## match or the field doesn't contain a string the field is ignored. pattern = "^/api(?P<method>/[\\w/]+)\\S*" ## Replacement expression defining the value of the target field. You can ## use regexp groups or named groups e.g. ${method} references the group ## named "method". replacement = "${method}" ## Name of the target field defaulting to 'key' if not specified. ## In case of wildcards being used in `key` the currently processed ## field-name is used as target. # result_key = "method" ## Rename metric fields [[processors.regex.field_rename]] ## Regular expression to match on the field name pattern = "^search_(\\w+)d$" ## Replacement expression defining the name of the new field replacement = "${1}" ## If the new field name already exists, you can either "overwrite" the ## existing one with the value of the renamed field OR you can "keep" ## both the existing and source field. # result_key = "keep" ## Rename metric tags [[processors.regex.tag_rename]] ## Regular expression to match on a tag name pattern = "^search_(\\w+)d$" ## Replacement expression defining the name of the new tag replacement = "${1}" ## If the new tag name already exists, you can either "overwrite" the ## existing one with the value of the renamed tag OR you can "keep" ## both the existing and source tag. # result_key = "keep" ## Rename metrics [[processors.regex.metric_rename]] ## Regular expression to match on an metric name pattern = "^search_(\\w+)d$" ## Replacement expression defining the new name of the metric replacement = "${1}"3.1 tags 与 fields 小节(值转换)
这两个小节用于转换 tag / field 的值,每个小节支持以下参数:
| 参数 | 必填 | 说明 |
|---|---|---|
key | 是 | 要处理的 tag / field 名称,支持 glob 表达式(如*)。对于tags/fields小节,这是唯一必填参数,缺少时会报key required错误(见 converter.go) |
pattern | 是 | 匹配 tag / field 值的正则表达式。若值不匹配,则跳过该 tag / field 不处理 |
replacement | 视情况 | 替换表达式,定义目标 tag / field 的新值。可使用捕获组(如${1}引用第 1 组)或命名组(如${mygroup}引用名为mygroup的组) |
result_key | 否 | 目标 tag / field 的名称,不指定时默认为key(即原地覆盖)。若key中使用了通配符,则以当前实际处理的 tag / field 名作为目标名 |
append | 否 | 仅对tags小节有效。设为true时,将replacement的结果追加到目标 tag 现有值之后,而不是覆盖它,默认false |
转换的触发条件(见 converter.go 与applyFields的实现):只有当 tag / field名称匹配key(使用 glob 匹配)且其值匹配pattern时才会应用转换;对于 field,还要求其值必须是string类型。任一条件不满足,该指标都不会被转换。
注意append的语义细节(见 converter.go):它是把replacement生成的新值拼接到目标 tag 已有值的后面,例如已有 tagverb=GET,替换结果为" OK"时,最终值变为GET OK。
3.2 field_rename 与 tag_rename 小节(名称重命名)
这两个小节用于对 tag / field 的名称进行批量重命名,与tags/fields小节的“值转换”在语义上不同。参数如下:
| 参数 | 说明 |
|---|---|
pattern | 匹配 tag / field 名称的正则表达式 |
replacement | 替换表达式,定义新名称 |
result_key | 可选,取值overwrite或keep(默认keep),用于控制新名称与已有名称冲突时的行为 |
冲突处理规则:
overwrite:用源 tag / field 覆盖已存在的目标 tag / field,且源 tag / field 无论如何都会被移除;keep(默认):当目标名称已存在时,目标与源 tag / field 都保持不变,不进行重命名。
需要指出的是,在这两个小节中配置key是无效的——插件在Init()阶段会打印日志提示'tag_rename'/'field_rename' section contains a key which is ignored during processing(见 regex.go)。另外从源码看,若result_key填了非法值(非overwrite/keep/空),Init()会返回错误invalid metrics result_key(见 converter.go)。
重命名实现上有一个值得了解的细节(见 converter.go):当目标名已存在且为overwrite模式时,替换操作会被延迟到遍历结束之后统一执行,因为不能在遍历 tag / field 列表的同时修改它,否则会引发内存访问问题(源码注释明确指出这会导致 invalid memory dereference panic)。
3.3 metric_rename 小节(指标名重命名)
与 tag / field 重命名类似,metric_rename用于重命名匹配pattern的指标名,新名称由replacement指定。与名称重命名小节不同:
- 只要指标名匹配
pattern,转换始终被应用(没有冲突判断逻辑,见 converter.go 中applyMetricRename的实现); result_key对指标名重命名无效,不应设置。若配置了result_key,Init()会打印日志提示其被忽略(见 regex.go)。
四、命名组批量处理(Batch Processing)
这是tags与fields小节特有的高级能力:使用命名组在一条转换规则中批量创建多个新 tag 或 field。用法要点:
pattern中的所有捕获组都必须命名(可以使用额外的非捕获组或其他正则表达式);- 此时不能设置
replacement和result_key,因为新 tag / field 的名称就是命名组的组名,值就是该组匹配到的内容。
从源码实现看,这一模式由setup()自动探测(见 converter.go):当ResultKey与Replacement均为空时,插件检查regexp.SubexpNames()返回的组名列表,若所有组都有名字则进入“named-group 模式”,否则打印警告并退回显式空替换模式。
进入命名组模式后,实际处理逻辑为(见 converter.go 与applyFields对应分支):对每个匹配的 tag / field,取出各命名组的匹配内容,逐个以组名为 key 新增 tag / field(空匹配的组会被跳过)。
五、实战示例:从一条 Nginx 访问日志指标说起
以下示例均基于仓库文档中的同一条输入指标(line protocol 格式):
nginx_requests,verb=GET,resp_code=200 request="/api/search/?category=plugins&q=regex&sort=asc",referrer="-",ident="-",http_version=1.1,agent="UserAgent",client_ip="127.0.0.1",auth="-",resp_bytes=270i 1519652321000000000其结构为:指标名nginx_requests,tags 为verb=GET、resp_code=200,fields 包含request(URL 字符串)、client_ip、resp_bytes(整数 270)等。
5.1 显式指定(Explicit specification)
[[processors.regex]] namepass = ["nginx_requests"] [[processors.regex.tags]] key = "resp_code" pattern = "^(\\d)\\d\\d$" replacement = "${1}xx" [[processors.regex.fields]] key = "request" pattern = "^/api(?P<method>/[\\w/]+)\\S*" replacement = "${method}" result_key = "method" [[processors.regex.fields]] key = "request" pattern = ".*category=(\\w+).*" replacement = "${1}" result_key = "search_category" [[processors.regex.field_rename]] pattern = "^client_(\\w+)$" replacement = "${1}"转换结果:
-nginx_requests,verb=GET,resp_code=200 request="/api/search/?category=plugins&q=regex&sort=asc",referrer="-",ident="-",http_version=1.1,agent="UserAgent",client_ip="127.0.0.1",auth="-",resp_bytes=270i 1519652321000000000 +nginx_requests,verb=GET,resp_code=2xx request="/api/search/?category=plugins&q=regex&sort=asc",method="/search/",category="plugins",referrer="-",ident="-",http_version=1.1,agent="UserAgent",ip="127.0.0.1",auth="-",resp_bytes=270i 1519652321000000000可以看到四个转换依次生效:tagresp_code被改写为2xx;fieldrequest的命名组method被抽取为新的 fieldmethod;第二个fields规则从 query 参数中抽取出category=plugins作为新 field;最后field_rename将client_ip重命名为ip。注意resp_bytes=270i是整数,完全不受影响。
5.2 追加模式(Appending)
[[processors.regex]] namepass = ["nginx_requests"] [[processors.regex.tags]] key = "resp_code" pattern = '^2\d\d$' replacement = " OK" result_key = "verb" append = true转换结果:
-nginx_requests,verb=GET,resp_code=200 request="/api/search/?category=plugins&q=regex&sort=asc",referrer="-",ident="-",http_version=1.1,agent="UserAgent",client_ip="127.0.0.1",auth="-",resp_bytes=270i 1519652321000000000 +nginx_requests,verb=GET\ OK,resp_code=200 request="/api/search/?category=plugins&q=regex&sort=asc",referrer="-",ident="-",http_version=1.1,agent="UserAgent",client_ip="127.0.0.1",auth="-",resp_bytes=270i 1519652321000000000这里把 resp_code 的匹配结果" OK"追加到已有 tagverb的GET之后,得到GET\ OK。
5.3 命名组批量抽取(Named groups)
[[processors.regex]] namepass = ["nginx_requests"] [[processors.regex.fields]] key = "request" pattern = '^/api/(?P<method>\w+)[/?].*category=(?P<category>\w+)&(?:.*)'转换结果:
-nginx_requests,verb=GET,resp_code=200 request="/api/search/?category=plugins&q=regex&sort=asc",referrer="-",ident="-",http_version=1.1,agent="UserAgent",client_ip="127.0.0.1",auth="-",resp_bytes=270i 1519652321000000000 +nginx_requests,verb=GET,resp_code=200 request="/api/search/?category=plugins&q=regex&sort=asc",method="search",category="plugins",referrer="-",ident="-",http_version=1.1,agent="UserAgent",client_ip="127.0.0.1",auth="-",resp_bytes=270i 1519652321000000000只配置了key和pattern,没有replacement/result_key。由于两个捕获组method与category均被命名,插件自动进入批量模式,一次抽出新 fieldmethod="search"与category="plugins"。
5.4 指标名重命名(Metric renaming)
[[processors.regex]] [[processors.regex.metric_rename]] pattern = '^(\w+)_.*$' replacement = "${1}"转换结果:
-nginx_requests,verb=GET,resp_code=200 request="/api/search/?category=plugins&q=regex&sort=asc",referrer="-",ident="-",http_version=1.1,agent="UserAgent",client_ip="127.0.0.1",auth="-",resp_bytes=270i 1519652321000000000 +nginx,verb=GET,resp_code=200 request="/api/search/?category=plugins&q=regex&sort=asc",referrer="-",ident="-",http_version=1.1,agent="UserAgent",client_ip="127.0.0.1",auth="-",resp_bytes=270i 1519652321000000000指标名nginx_requests被改写为nginx,其余 tag / field 均保持不变。该规则未使用namepass,说明它会对所有流入指标生效,因此实践中通常需要配合namepass/namedrop来限定范围。
六、源码实现与工作流程
6.1 处理顺序
从 regex.go 中Apply()的实现可以看出,处理器对每条指标按配置顺序依次执行五类转换:先全部tags,再全部fields,然后是全部tag_rename、field_rename,最后是所有metric_rename。这意味着:
- 后配置的
tags规则可以看到前面规则产生的新 tag; - 同一小节内的多条规则之间存在先后依赖关系,可以像流水线一样串联(仓库测试 TestMultipleConversions 就验证了
resp_code→resp_code_group→resp_code_text的链式转换)。
6.2 初始化与错误处理
Init()阶段(见 regex.go)完成以下工作:
- 为每个转换器预编译正则表达式(
regexp.Compile),若正则有语法错误,Init()直接返回错误并指明出错的小节(如'tags' ...),插件将无法启动; - 为
tags/fields小节通过filter.Compile编译key的 glob 过滤器; - 校验
result_key取值,决定是否进入命名组批量模式。
6.3 类型安全与性能
applyFields中通过 Go 类型断言value, ok := field.Value.(string)确认 field 值为字符串,非字符串直接跳过(见 converter.go)——这正是文档开头“只操作字符串 field”限制的实现来源;- 正则表达式在
Init()时一次性编译、处理时复用,避免每条指标重复编译;仓库还提供了基准测试 BenchmarkConversions 用于评估转换开销; - 处理器采用跟踪指标感知的写法,TestTrackedMetricNotLost 验证了经
metric.WithTracking包装的指标在转换并Accept()后投递信息(DeliveryInfo)不会丢失。
6.4 通配符与匹配语义
key支持 glob 表达式。当使用*时,会匹配指标上所有 tag / field 名(由filter.Compile实现),配合值正则即可实现“对所有字段做同一类清洗”。仓库测试 TestAnyTagConversion 展示了用key = "*"配合 UUID 正则对所有 tag 做脱敏([0-9a-f]{8}-...→{UUID}),TestAnyFieldConversion 则用key = "*"将所有字符串 field 中的四位数字替换为{ID},同时验证了整数 fieldcounter不被触碰。
七、与同类处理器及文档的配合使用
regex处理器通常与以下配置组合使用以获得最佳效果:
- 全局过滤:用
namepass限定指标范围,用tagpass/fieldpass进一步限定 tag / field 范围,详见 docs/CONFIGURATION.md#plugins; - 处理器顺序:Telegraf 支持通过
order配置处理器执行顺序,可参考仓库中的处理器排序测试用例 agent/testcases/processor-order-explicit 与 agent/testcases/processor-order-appearance 理解其语义; - 管道协作:若需要更复杂的字符串处理(如模板化、脚本化逻辑),可以结合其他 processor 使用;而
regex的定位始终是“轻量、高性能、纯正则”的原地转换。
八、常见问题与注意事项
- field 是数字或布尔值为什么不生效?因为插件通过类型断言只处理
string类型 field,数字、布尔等类型会被静默跳过。若确需处理,可先在管线中通过其他方式将其转换为字符串。 - 命名组模式下为什么必须给所有捕获组命名?因为命名组模式的触发条件要求
result_key与replacement均为空且所有捕获组都有名字;存在未命名组时会回退到“显式空替换”模式并打印警告,行为可能不符合预期。 result_key与append的适用性:append仅对tags小节有意义;metric_rename不支持result_key;field_rename/tag_rename的result_key只接受overwrite与keep。- 正则转义:TOML 双引号字符串中反斜杠需要转义(如
"^(\\d)\\d\\d$"),单引号字面量字符串则不需要(如'^2\d\d$'),示例中两种写法均出现过。 - 指标被覆盖而非新增:
tags/fields小节不指定result_key时是原地覆盖值;想保留原始值请用result_key输出到新名称。
九、相关资源
- 插件说明文档:plugins/processors/regex/README.md
- 插件主实现:plugins/processors/regex/regex.go
- 转换器与匹配逻辑实现:plugins/processors/regex/converter.go
- 完整示例配置:plugins/processors/regex/sample.conf
- 单元测试与基准测试:plugins/processors/regex/regex_test.go
- 全局配置与插件过滤选项:docs/CONFIGURATION.md#plugins
【免费下载链接】telegrafAgent for collecting, processing, aggregating, and writing metrics, logs, and other arbitrary data.项目地址: https://gitcode.com/GitHub_Trending/te/telegraf
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考