Telegraf:Go 语言采集代理

导航至

采集代理是任何监控基础设施的关键组成部分:它们可以在您的主机上运行,收集关于您的系统和应用程序的数据,或者它们可以远程操作,通过您的应用程序暴露的端点在网络上收集数据。

2015 年,InfluxData 发布了 Telegraf:一个轻量级、插件驱动的采集代理,用 Go 语言编写。虽然许多开发者已经在使用各种采集代理将指标发送到 InfluxDB 和其他时间序列数据库,但 InfluxData 想要一个围绕标签测量概念设计的项目,这种数据模型用于像 InfluxDB 和 OpenTSDB 这样的数据库。

Telegraf 具有基于插件的架构,其设计旨在让用户可以轻松地为项目贡献功能,而无需了解任何关于代码库的知识。Telegraf 中有四种不同类型的插件:输入处理器聚合器输出 插件,每种插件处理数据路径的一部分。自 2015 年成立以来,Telegraf 插件的数量已增长到 150 多个——其中大部分由社区贡献——这使得 Telegraf 能够从各种输入源收集指标,并将它们写入各种输出目标。

一些插件示例

  • postgresql — 一个输入插件,用于收集关于您的 Postgres 安装的性能指标。它使用来自内置的 pg_stat_databasepg_stat_bgwriter 视图的数据。
  • apache — 一个输入插件,使用 mod_status 模块收集服务器性能信息 Apache HTTP 服务器
  • prometheus — 一个输入插件,用于从以 Prometheus 格式暴露指标的 HTTP 服务器收集指标。
  • influxdb — 一个输出插件,通过 HTTP 或 UDP 写入 InfluxDB
  • opentsdb — 一个输出插件,使用 "telnet" 或 HTTP 模式写入 OpenTSDB 实例

使用 Telegraf

如果您想运行 Telegraf,首先 安装 Telegraf

Telegraf 能够根据您指定的插件生成配置文件。您可以在运行 Telegraf 时使用 -sample-config 参数创建一个新配置

$ telegraf -sample-config -input-filter apache -output filter influxdb > telegraf.conf

这将在您的工作目录中创建一个 telegraf.conf 文件。接下来,您可以使用新配置启动 Telegraf

$ telegraf -config telegraf.conf

如果您将 Telegraf 作为服务运行,您需要将新生成的配置文件放入相应的目录(例如 Linux 上的 /etc/telegraf),并重启 Telegraf。在 Debian / Ubuntu 上,配置文件将放在 /etc/telegraf 中,而 Telegraf 本身可以使用 systemctl restart telegraf 重启。

接口和编写插件

插件在 Telegraf 中使用 Go 接口实现。每种插件类型都由一个接口定义,编写新插件就像实现这些接口并将您的插件导入到主 Telegraf 包中一样容易。

如果您创建了一个新插件,或者修复或添加了现有插件的功能,请在 GitHub 上提交 PR 并分享您的辛勤工作!贡献者还需要一些额外的步骤,例如添加适当的文档和测试,您可以在 Telegraf 代码库的 贡献文档 中找到更多信息。

该文档还包含关于编写作为 Telegraf 一部分的不同的插件接口的详细信息。

入门

如果您有兴趣开发自己的 Telegraf 插件,您需要在您的机器上安装 Go 1.5+。Golang 网站有一个很好的 入门 指南,其中包含安装说明和下载页面链接。

安装 Go 后,使用 go get 下载 Telegraf 源代码,在 git 中检出一个新分支进行您的工作,并尝试使用 make 构建二进制文件

$ go get github.com/influxdata/telegraf
$ cd $GOPATH/github.com/influxdata/telegraf
$ git checkout -b MyPlugin $ make

源代码将下载到您的 Gopath 中的 src 目录中,而 make 命令将在 bin 目录下创建一个 Telegraf 二进制文件。

让我们看一下一个现有的示例。Telegraf 有一个名为 Trig 的插件,它通常用于演示目的,并根据三角函数正弦和余弦发出数据。我们将在下一节中逐步完成创建 Trig 插件的过程。

输入插件

首先,将以下行添加到 telegraf/plugins/inputs/all/all.go

github.com/influxdata/telegraf/plugin/inputs/trig

以导入您的插件并确保 Telegraf 可以运行您编写的代码。由于任何创建插件的人都需要编辑此文件,因此当您准备合并您的代码时,您可能会遇到合并冲突。但是,在开始本地开发之前添加此信息至关重要——没有它,您编写的代码将无法运行。

Telegraf 的输入插件只需要满足三个接口。来自 Godoc

type Input interface { 
     // SampleConfig returns the default configuration of the Input 
     SampleConfig() string
     // Description returns a one-sentence description on the Input 
     Description() string
     // Gather takes in an accumulator and adds the metrics that the Input 
     // gathers. This is called every "interval" 
     Gather(Accumulator) error }

DescriptionSampleConfig 都被 Telegraf 用于生成配置文件。Telegraf 配置使用 TOML 编写;每个部分都以一个单行注释开头,其中包含 Description() 函数返回的字符串,后跟插件本身的配置变量,由 SampleConfig() 函数返回。

插件配置有一个变量,amplitude

# Inserts sine and cosine waves for demonstration purposes 
[[inputs.trig]] 
  ## Set the amplitude 
  amplitude = 10.0

这是来自 trig.go 的实现

var TrigConfig = ` 
  ## Set the amplitude 
  amplitude = 10.0 
` 

func (s *Trig) SampleConfig() string { 
     return TrigConfig 
} 

func (s *Trig) Description() string { 
     return "Inserts sine and cosine waves for demonstration purposes" 
}

注意:在编写 TOML 配置时,请确保使用两个空格而不是制表符来缩进一行,以便当 Telegraf 生成配置时,您的条目与其他条目对齐。

输入插件的最后一个接口方法是 Gather。这是我们将完成与从输入收集数据相关的所有工作的地方。此时它返回 nil,因为我们还没有向 Gather 方法添加任何代码,但我们可以继续构建 Telegraf 并测试生成配置以确保它有效。

在您的工作目录中输入

$ make $ telegraf -sample-config -input-filter trig -output-filter influxdb -debug

-debug 标志将向输出添加额外的信息,以帮助识别您可能遇到的任何问题。

您应该在输出底部看到这个

# 
# INPUTS: 
# 

# Inserts sine and cosine waves for demonstration purposes 
[[inputs.trig]] 
  # Sets the amplitude 
  amplitude = 10.0

由于我们在配置中添加了一个配置参数,我们还需要向我们的 struct 添加一个相应的属性。您将在 trig.go 中看到以下行

type Trig struct { 
     x float64 
     Amplitude float64 
}

其中 Amplitude 是我们在配置中定义的值,而 x 是一个变量,用于在收集间隔之间存储插件状态。

在我们的配置经过测试并工作,并且将适当的属性添加到我们的 struct 之后,我们准备为 Gather 方法创建实现。

Telegraf 定期收集指标并将指标“刷新”到您的输出;收集和刷新间隔都可以在 Telegraf 配置的 [agent] 部分下定义,使用 intervalflush_interval 变量,因此如果您将前者设置为 1s,后者设置为 10s,则 Trig 插件将每秒生成新点,但您要等到 Telegraf 每十秒将数据刷新到数据库后才能看到它们出现。

Gather() 方法接受一个参数,即 telegraf.Accumulator,它通过 telegraf.Accumulator.AddFields(measurement, tags, fields) 方法处理新测量的创建。此方法接受三个参数:一个 measurement,它是一个 stringtags,它是一个 map[string]string,其中键和值都是字符串;以及 fields,它是一个 map[string]interface{},它的键是字符串,字段可以是任何东西。

让我们看一下 Trig 的 Gather 方法

func (s *Trig) Gather(acc telegraf.Accumulator) error {
     sinner := math.Sin((s.x*math.Pi)/5.0) * s.Amplitude 
     cosinner := math.Cos((s.x*math.Pi)/5.0) * s.Amplitude 

     fields := make(map[string]interface{}) 
     fields["sine"] = sinner 
     fields["cosine"] = cosinner 

     tags := make(map[string]string) 

     s.x += 1.0 
     acc.AddFields("trig", fields, tags) 

     return nil 
}

首先,我们使用先前的值以及我们在配置中定义的振幅,在我们的正弦波和余弦波上生成一个新点。然后,我们创建我们的字段和标签,并分配适当的信息,然后更新我们的状态以供下次调用 Gather 之前使用,然后调用 AddFields 以生成我们的测量。

注意:在设计 Telegraf 插件时,设计良好的模式非常重要。要记住的一个常见问题是所谓的“序列基数”,它是您在数据库中存储的唯一序列的数量。如果您生成大量标签,例如通过为每个测量分配一个 UUID,您可能会快速达到大量序列,这将对数据库的内存使用率和性能产生影响。

Trig 插件需要的最后一件事是起始状态,我们将在 trig.goinit 函数中定义它

func init() {
     inputs.Add("trig", func() telegraf.Input { return &Trig{x: 0.0} }) 
}

此函数接受整个插件并将其传递给 Telegraf 代理,然后 Telegraf 代理在每次收集间隔过去时迭代所有活动插件,并在每次收集间隔过去时调用 Gather 函数。

是时候测试了!让我们重新生成我们的配置并运行 Telegraf

$ make 
$ telegraf -sample-config -input-filter trig -output-filter influxdb >> telegraf.conf.test 
$ telegraf -config telegraf.conf.test -debug

调试输出将显示插件正在运行并收集指标。

此时您还应该为您的插件编写一些测试。如果您想向上游贡献您的插件,这是一个要求。每次有新构建时都会运行测试,以捕获可能已引入的任何类型的回归或问题。在 Go 中,测试很容易编写并且是语言原生的。您将编写传入测试 struct 的方法,并使用它来断言您的插件的行为。您可以在相应的 trig_test.go 文件中找到 trig.go 的测试 (在 GitHub 上这里是)。

贡献

除了测试之外,您还需要为您的插件创建一个 README.md 文件,其中包含关于您的插件做什么的信息。您还需要确保您有一个 LICENSE 文件以及输入/输出格式的示例。如果您的插件有其他依赖项,您还需要添加这些依赖项。再次强调,如果您有兴趣贡献,请查看 GitHub 上的优秀指南