Telegraf 外部插件(External Plugins)开发指南:借助 execd 与 Execd Go Shim 扩展插件生态
2026/9/13 15:02:58 网站建设 项目流程

Telegraf 外部插件(External Plugins)开发指南:借助 execd 与 Execd Go Shim 扩展插件生态

【免费下载链接】telegrafAgent for collecting, processing, aggregating, and writing metrics, logs, and other arbitrary data.项目地址: https://gitcode.com/GitHub_Trending/te/telegraf

Telegraf 的插件系统虽然以 Go 编写、随主仓库统一发布,但通过execd机制,任何人都可以在 Telegraf 之外用任意语言编写、构建并运行独立的输入(input)、处理器(processor)与输出(output)插件,本文即围绕这一机制展开。读完本文,你将掌握外部插件的设计动机、execd三类插件(inputs.execd / processors.execd / outputs.execd)的接入方式、以及如何借助plugins/common/shim把 Telegraf 内置插件一键"外部化"并独立构建运行。

什么是 Telegraf 外部插件

外部插件(External Plugins)指在 Telegraf 主仓库之外构建的外部程序,它们不随 Telegraf 二进制编译,而是通过execd插件作为独立进程被 Telegraf 拉起,以标准输入(stdin)/ 标准输出(stdout)与 Telegraf 通信。官方入口文档位于 docs/EXTERNAL_PLUGINS.md,完整收录清单见仓库根目录的 EXTERNAL_PLUGINS.md。

相比只能在 Telegraf 内部用 Go 编写的内置插件,外部插件提供了显著更大的灵活性:

  • 语言自由:外部插件可以用任意语言编写(内置插件只能用 Go);
  • 库生态不受限:可以访问非 Go 语言的库,包括需要 CGO 支持的第三方库;
  • 可引入闭源软件:能够利用不开放给开源社区的许可软件;
  • 控制二进制体积:可以携带大型依赖,而不会撑大 Telegraf 本身的发布体积;
  • 发布节奏自主:不必等待 Telegraf 团队发布插件即可开始使用;
  • 内外转换简单:借助 shim,可以轻松在内部插件与外部插件之间互相转换。

需要强调的是,外部插件并不豁免插件作者的职责:外部插件的作者同时负责其维护与功能迭代,用户大概率会在其各自的仓库上直接提交 issue(见 docs/EXTERNAL_PLUGINS.md 中的说明)。

外部插件的通信载体:execd 插件家族

外部程序之所以能接入 Telegraf,依靠的是三个execd插件,它们是外部插件在 Telegraf 侧的"宿主":

插件通信方向说明
inputs.execd进程 stdout → Telegraf将外部程序作为常驻守护进程,从 stdout 按数据格式读取指标
processors.execdTelegraf stdin → 进程 → stdout将指标通过 stdin 送入外部进程,再从 stdout 读回处理结果
outputs.execdTelegraf stdin → 进程将指标写入外部守护进程的 stdin,由外部程序负责写出

inputs.execd:把外部程序当作指标源

inputs.execd 运行给定的外部程序作为长驻守护进程,并按 docs/DATA_FORMATS_INPUT.md 中列出的数据格式解析进程 stdout 上的指标。程序预期持续运行,并在收到配置的signal时输出数据。进程的stderr会被转发到 Telegraf 日志,默认按 error 级别记录;也可以用E!(error)、W!(warning)、I!(info)、D!(debug)、T!(trace)前缀加空格来控制日志级别,例如输出I! A log message会在 Telegraf 日志中生成一条 info 记录。其最小支持版本为 Telegraf v1.14.0,示例配置见 sample.conf:

# Run executable as long-running input plugin [[inputs.execd]] ## One program to run as daemon. ## NOTE: process and each argument should each be their own string command = ["telegraf-smartctl", "-d", "/dev/sda"] ## Environment variables ## Array of "key=value" pairs to pass as environment variables # environment = [] ## Define how the process is signaled on each collection interval. ## Valid values are: ## "none" : Do not signal anything. (Recommended for service inputs) ## The process must output metrics by itself. ## "STDIN" : Send a newline on STDIN. (Recommended for gather inputs) ## "SIGHUP" : Send a HUP signal. Not available on Windows. (not recommended) ## "SIGUSR1" : Send a USR1 signal. Not available on Windows. ## "SIGUSR2" : Send a USR2 signal. Not available on Windows. # signal = "none" ## Delay before the process is restarted after an unexpected termination # restart_delay = "10s" ## Buffer size used to read from the command output stream ## Optional parameter. Default is 64 Kib, minimum is 16 bytes # buffer_size = "64Kib" ## Disable automatic restart of the program and stop if the program exits ## with an error (non-zero error code) # stop_on_error = false ## Data format to consume. # data_format = "influx"

signal是 input 场景下最关键的选项:对于按采集周期主动 gather 的程序建议用"STDIN"(每次向 stdin 发送一个换行触发采集),对于自行持续输出指标的 service 型程序建议用"none"。仓库中附带四种语言的示例程序,可对照不同 signal 用法:count.go(期望SIGHUP)、count.py(none)、count.rb(none)、count.sh(STDIN)。

processors.execd:把外部程序当作流式处理器

processors.execd 将指标通过 stdin 送入外部进程,并从其 stdout 读回处理后的指标,stderr输出会被记录到日志。它有两个重要注意点(见其 README):

  • 带追踪(tracking)的指标在传入外部进程那一刻即被视为"已投递",目前无法将 execd 进程输出的指标与进入的指标一一对应(处理器可能增删指标且全程异步);
  • 目前只能使用data_format = "influx",因为必须要求序列化-解析对称且不丢失关键类型数据。

其配置结构如下(完整示例见 sample.conf):

# Run executable as long-running processor plugin [[processors.execd]] ## One program to run as daemon. ## NOTE: process and each argument should each be their own string ## eg: command = ["/path/to/your_program", "arg1", "arg2"] command = ["cat"] ## Environment variables # environment = [] ## Delay before the process is restarted after an unexpected termination # restart_delay = "10s" ## Serialization format for communicating with the executed program # data_format = "influx"

README 中还给出了一个完整的 Go 守护进程示例:用influx.NewStreamParser(os.Stdin)逐条解析 stdin 上的指标,读取count字段乘以 2 后再用serializers_influx.Serializer写回 stdout——这正是外部处理器插件的典型实现模式。配套测试用例位于 plugins/processors/execd/testcases,其中dataformat-influxdataformat-jsondefaults等目录各含telegraf.confinput.influx,可作为端到端联调参考。

outputs.execd:把外部程序当作写出目标

outputs.execd 将指标写入外部守护进程的 stdin,命令只执行一次,之后每次写入都以指定数据格式传入(支持格式见 docs/DATA_FORMATS_OUTPUT.md)。其配置(见 sample.conf)还包括两个输出侧特有选项:

# Run executable as long-running output plugin [[outputs.execd]] command = ["my-telegraf-output", "--some-flag", "value"] # environment = [] restart_delay = "10s" ## Flag to determine whether execd should throw error when part of metrics is unserializable # ignore_serialization_error = false ## Use batch serialization instead of per metric. # use_batch_format = false data_format = "influx"

该插件的错误处理模型需要特别注意(其 README 有专门说明):它采用fire-and-forget通信模型,指标一旦写入外部进程的 stdin 管道即被视为写入成功,而不是等到外部插件真正处理完毕。由于操作系统管道缓冲(通常约 64KB),写入 stdin 在缓冲区填满前都是非阻塞的;外部插件出错时只会向 stderr 写错误信息(Telegraf 负责记录),不会触发 Telegraf 的重试机制,也不阻止指标从缓冲区移除——因此指标可能丢失。若需要可靠投递,应改用内置输出插件,或在外部插件内部自行实现确认机制。仓库附带的 file.sh 与 redis_influx.rb 等示例可帮助你快速上手。

Execd Go Shim:把内置插件一键"外部化"

对于 Go 插件,仓库提供了 Execd Go Shim,其目标是把 Telegraf 主仓库中的内部 input、processor、output 插件轻松抽取到独立仓库,任何人都可以把它构建成独立应用,再经由上述三类execd插件接入 Telegraf。

shim 的核心实现

shim 的核心类型在 goshim.go 中定义。Shim结构体同时持有三种插件接口:

type Shim struct { Input telegraf.Input Processor telegraf.StreamingProcessor Output telegraf.Output BatchSize int BatchTimeout time.Duration ... }

它暴露的Run(pollInterval)方法会按"输入 → 处理器 → 输出"的优先级只运行一种插件(goshim.goRun的实现依次检查s.Inputs.Processors.Output,都不为空才返回errors.New("nothing to run")),这也解释了文档中"每个仓库只放一个插件"的建议——shim 并非为同时运行多个插件而设计。输入型插件采集到的指标经由writeProcessedMetrics用 influx 序列化器编码后写入 stdout,这与inputs.execd的读取协议完全对应。

配置加载逻辑见 config.go:LoadConfig读取 TOML 配置后,从plugins/inputsplugins/processorsplugins/outputs各自的注册表中按名字查找插件构造器并解码配置;当未指定配置文件时,DefaultImportedPlugins会直接加载所有被 import 进来的插件并打印No config found. Loading default config for plugin ...日志。配置文件中的环境变量(如$VAR${VAR})会在读取时通过os.Expand展开,便于按环境注入敏感配置。

示例入口程序

shim 自带的可直接复制的入口程序位于 plugins/common/shim/example/cmd/main.go,其关键结构为:

package main import ( "flag" "fmt" "os" "time" // TODO: import your plugins _ "github.com/influxdata/tail" // Example external package for showing where you can import your plugins "github.com/influxdata/telegraf/plugins/common/shim" ) var pollInterval = flag.Duration("poll_interval", 1*time.Second, "how often to send metrics") var pollIntervalDisabled = flag.Bool( "poll_interval_disabled", false, "set to true to disable polling. You want to use this when you are sending metrics on your own schedule", ) var configFile = flag.String("config", "", "path to the config file for this plugin") func main() { flag.Parse() if *pollIntervalDisabled { *pollInterval = shim.PollIntervalDisabled } shimLayer := shim.New() // If no config is specified, all imported plugins are loaded. if err = shimLayer.LoadConfig(configFile); err != nil { fmt.Fprintf(os.Stderr, "Err loading input: %s\n", err) os.Exit(1) } if err = shimLayer.Run(*pollInterval); err != nil { fmt.Fprintf(os.Stderr, "Err: %s\n", err) os.Exit(1) } }

shim.PollIntervalDisabled(值为time.Duration(0))用于显式禁用轮询,适合"按自身节奏推送指标"的程序,与内置常量定义一致(见 goshim.go)。对应的插件配置文件模板为 plugin.conf:

[[inputs.my_plugin_name]] value_name = "value"

分步指南:将插件外部化并与 execd 对接

官方文档 docs/EXTERNAL_PLUGINS.md 提供了完整的七步流程,这也是把插件(无论是新写的还是从内置迁移的)接入execd的标准路线:

  1. 编写 Telegraf 插件。根据插件类型,遵循 InfluxData 的最佳实践指南来创建插件本体:
    • 输入插件:docs/INPUTS.md
    • 处理器插件:docs/PROCESSORS.md
    • 聚合器插件:docs/AGGREGATORS.md
    • 输出插件:docs/OUTPUTS.md
  2. 将项目迁移到外部仓库。建议保留原有的路径结构(并非强制)。例如插件原在plugins/inputs/cpu,则新仓库中也建议放在plugins/inputs/cpu下,便于社区对照与维护。
  3. 复制入口程序。把 plugins/common/shim/example/cmd/main.go 复制到项目cmd目录下,作为独立运行时的入口点,它会自动调用 shim 代码。再次强调:一个仓库只放一个插件,因为 shim 不支持同时运行多个插件。
  4. 修改 main.go 导入你的插件。在 Telegraf 内部,这一般由all.go完成,但外部化时直接写在 main.go 顶部即可。跳过这一步插件将什么都不做,形式如:

    _ "github.com/me/my-plugin-telegraf/plugins/inputs/cpu"

  5. (可选)添加插件专属配置plugin.conf。注意该配置文件必须与 Telegraf 其余配置分离,不能放在 Telegraf 加载所有配置的共享目录中——如果 Telegraf 读到了这个文件,它不知道该文件对应哪个插件。Telegraf 是通过execd配置块来定位这个插件的。
  6. 在仓库主页补充使用与开发说明,内容应涵盖:
    1. 如何下载对应平台的发布包,或如何 clone 外部插件的二进制;
    2. 构建二进制的命令;
    3. 需要编辑的telegraf.conf位置;
    4. 与 inputs.execd、processors.execd 或 outputs.execd 配合使用的完整配置。
  7. 提交插件。通过 Pull Request 将外部插件加入 EXTERNAL_PLUGINS.md 清单,需要包含:插件名称、插件仓库链接、以及一段简短描述。

构建与运行外部插件

构建二进制

对 Go 插件(使用 shim),构建非常简单:

go build -o rand cmd/main.go

rand示例项目为例,即生成可独立运行的rand二进制。

独立测试(不依赖 Telegraf)

  • 输入插件:直接运行二进制即可测试。例如./rand -config plugin.conf。根据轮询设置以及你实现的是 service 插件还是 gather 型插件,数据可能立即出现、也可能需要先按回车或等待一个轮询周期,指标会写到 STDOUT,用Ctrl-C结束测试。
  • 处理器 / 输出插件:同样可以手动测试,但需要在 STDIN 上喂入合法的指标,以便验证插件行为是否符合预期。这是接入 Telegraf 之前非常有价值的调试手段。

接入 Telegraf

构建完成后,在 Telegraf 配置中通过execd块调用新二进制。以输入插件为例(详见 plugins/common/shim/README.md):

[[inputs.execd]] command = ["/path/to/rand", "-config", "/path/to/plugin.conf"] signal = "none"

结合前文inputs.execd的完整配置项(environmentrestart_delaybuffer_sizestop_on_errordata_format等),即可正式投产。

已收录的外部插件生态一览

仓库根目录 EXTERNAL_PLUGINS.md 维护着社区贡献的外部插件清单(Pull Request 长期欢迎),可作为参考实现与选型来源:

  • 输入类(Inputs):如awsalarms(AWS 告警采集)、octoprint(3D 打印信息)、opcda(OPC DA 工业自动化协议)、plex(Plex 媒体服务器 Webhook)、rand(随机数生成)、systemd-timings(systemd 启动与单元时间戳指标)、twitter/youtube(账号信息)、dnsmasqx509_crl(X509 CRL 文件)、s7comm(西门子 PLC)、oracle/db2(关系型数据库统计)、apt(Debian 包更新检查)、knot(Knot DNS 统计)、linux-psi(内核压力停滞信息)、bacnet(BACnet 设备)、tado/homekit(智能家居)等;
  • 输出类(Outputs):如kinesis(Amazon Kinesis 聚合压缩)、firehose(Kinesis Data Firehose 批量发送)、playfab(Azure PlayFab);
  • 处理器类(Processors):如geoip(为 IP 附加 GeoIP 信息)、metadata(追加 OpenStack 元数据)。

这些插件全部通过execd三种插件之一接入 Telegraf,可直接对照研究其仓库结构、main.go 与配置组织方式。

总结

外部插件机制是 Telegraf 插件体系的重要延伸:一方面通过inputs.execdprocessors.execdoutputs.execd三个宿主插件,让任何语言的程序都能作为一等公民参与指标采集、处理与写出;另一方面通过 Execd Go Shim,让 Go 插件的"内置 ↔ 外部"转换成本降到最低——只需复制入口 main.go、import 插件、构建二进制并配置execd块。外部插件在带来语言自由、依赖自主和发布灵活的同时,也要求作者承担完整的维护与文档职责,尤其要理解outputs.execd的 fire-and-forget 语义可能带来的数据丢失风险。对于希望扩展 Telegraf 能力边界的开发者而言,从 EXTERNAL_PLUGINS.md 中的成熟案例入手,再依据 docs/EXTERNAL_PLUGINS.md 的七步流程发布自己的插件,是最稳妥的路径。

【免费下载链接】telegrafAgent for collecting, processing, aggregating, and writing metrics, logs, and other arbitrary data.项目地址: https://gitcode.com/GitHub_Trending/te/telegraf

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

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

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

立即咨询