Telegraf Datadog Output 插件实战:配置详解、指标转换规则与 rate_interval 原理
2026/9/14 17:59:52 网站建设 项目流程

Telegraf Datadog Output 插件实战:配置详解、指标转换规则与 rate_interval 原理

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

本篇围绕 Telegraf 的outputs.datadog插件展开,系统讲解如何通过 Datadog Metrics API(v1)将 Telegraf 采集的指标写入 Datadog:从完整的 TOML 配置项逐一解析(apikey、timeout、url、代理、压缩、rate_interval),到源码级的指标命名、类型映射与数值转换规则,再到rate_interval将 statsd 计数器转换为 rate 的底层实现与测试验证。读完后你可以独立完成该插件的配置、排错,并能准确预判每个 Telegraf 字段在 Datadog 侧最终呈现的指标名与指标类型。

插件定位:面向 Datadog Metrics API v1 的输出插件

Datadog Output 插件将 Telegraf 指标写入 Datadog Metrics API,前提是持有一个有效的apikey(在 Datadog 账户设置中获取)。插件文档(plugins/outputs/datadog/README.md)明确注明了版本适用边界:

This plugin supports the v1 API.

这一限制在源码中同样得到印证。datadog.go 定义了默认写入端点:

const datadogAPI = "https://app.datadoghq.com/api/v1/series"

而在插件注册时(init 函数)设置了两个关键默认值:

func init() { outputs.Add("datadog", func() telegraf.Output { return &Datadog{ URL: datadogAPI, Compression: "none", } }) }

即:默认请求https://app.datadoghq.com/api/v1/series,默认不做压缩。认证方式是把apikey作为查询参数拼在 URL 上(见下文“认证机制”一节),这也是文档注释中“由于认证方式限制,目前只支持 v1 API”的原因。

完整配置项详解

以下为插件的官方示例配置,完整保留自 sample.conf:

# Configuration for DataDog API to send metrics to. [[outputs.datadog]] ## Datadog API key apikey = "my-secret-key" ## Connection timeout. # timeout = "5s" ## Write URL override; useful for debugging. ## This plugin only supports the v1 API currently due to the authentication ## method used. # url = "https://app.datadoghq.com/api/v1/series" ## Set http_proxy # use_system_proxy = false # http_proxy_url = "http://localhost:8888" ## Override the default (none) compression used to send data. ## Supports: "zlib", "none" # compression = "none" ## When non-zero, converts count metrics submitted by inputs.statsd ## into rate, while dividing the metric value by this number. ## Note that in order for metrics to be submitted simultaneously alongside ## a Datadog agent, rate_interval has to match the interval used by the ## agent - which defaults to 10s # rate_interval = 0s

下面逐项说明各配置的含义、默认值与源码中的作用位置(对应 Datadog 结构体 中的字段):

apikey(必填)

Datadog 的 API 密钥,是唯一的强制配置。Connect 方法 在插件启动连接时会做显式校验:

func (d *Datadog) Connect() error { if d.Apikey == "" { return errors.New("apikey is a required field for datadog output") } ... }

未配置apikey时插件会直接报错,不会静默启动。

timeout

连接超时,TOML 时长格式(如"5s")。它对应config.Duration类型(定义见 config/types.go),解析时兼容整数秒、浮点秒以及"3s"这类时长字符串。Connect时它被设为http.ClientTimeout,控制单次写请求的最大耗时。

url(调试用 URL 覆盖)

默认指向https://app.datadoghq.com/api/v1/series,可覆盖为任意地址,典型用途是把请求打到本地 mock 服务做调试。测试 TestUriOverride 正是利用httptest.NewServer起了一个本地假服务,把url指向它来验证覆盖生效、请求能成功发出并收到 200。

代理配置:use_system_proxy / http_proxy_url

这两个选项来自 Telegraf 公共代理组件 plugins/common/proxy/proxy.go,其HTTPProxy结构体被内嵌进Datadog

  • use_system_proxy = true:使用环境变量(http.ProxyFromEnvironment,即HTTP_PROXY/HTTPS_PROXY等);
  • http_proxy_url:显式指定代理地址,会做 URL 解析校验,非法地址在Connect阶段报错;
  • 两者都不设置时不走代理。

compression:zlib 或 none

覆盖默认(none)的压缩方式,仅支持"zlib""none"两个取值。Write 方法 中的处理逻辑:

  • compression = "zlib":通过 internal/content_coding.go 的NewContentEncoder创建 zlib 编码器压缩 JSON 负载,并设置请求头Content-Encoding: deflate
  • compression = "none"(或任何其他值,走default分支):直接发送原始 JSON。

注意请求的Content-Type始终为application/json,压缩只作用于请求体传输编码。TestCompressionOverride 验证了 zlib 模式下请求可被本地服务正常接收。

rate_interval:把 count 指标转换为 rate

这是本插件最有技术含量的一项配置,后文专门展开。

此外,与 Telegraf 其他 output 一样,[[outputs.datadog]]还支持全局的插件级过滤配置(如namepass/nameprefix/tagpass、字段过滤等),详见 docs/CONFIGURATION.md 的 Plugins 章节。

数据流与请求格式:从 Telegraf Metric 到 Datadog Series

理解该插件最快的方式是看它发送给 Datadog 的 JSON 结构。datadog.go 定义了完整的序列化模型:

type TimeSeries struct { Series []*Metric `json:"series"` } type Metric struct { Metric string `json:"metric"` Points [1]Point `json:"points"` Host string `json:"host"` Type string `json:"type,omitempty"` Tags []string `json:"tags,omitempty"` Interval int64 `json:"interval"` } type Point [2]float64

即整个批次包成一个{"series": [...]},每条Metric只携带一个数据点Point(二元数组:[时间戳(秒), 值]),并带有指标名、host、类型、标签与 interval。

Write 方法 的完整流程:

  1. 调用convertToDatadogMetric把整批[]telegraf.Metric转换为[]*Metric;若结果为空(例如所有字段都是非法值被跳过),直接返回 nil,不发请求;
  2. json.Marshal序列化,失败则返回unable to marshal TimeSeries错误;
  3. compression决定是否 zlib 压缩;
  4. authenticatedURL()发起POST
  5. 校验响应状态码,仅200–209视为成功,否则读取响应体并返回received bad status code, <code>: <body>

TestBadStatusCode 用 500 响应验证了错误信息会携带 Datadog 返回的原始错误 JSON,例如{"errors": ["Something bad happened to the server."]}

认证机制与 API Key 防泄漏

apikey不走 Header,而是作为查询参数附加在 URL 上:

func (d *Datadog) authenticatedURL() string { q := url.Values{ "api_key": []string{d.Apikey}, } return fmt.Sprintf("%s?%s", d.URL, q.Encode()) }

TestAuthenticatedUrl 断言其输出为<url>?api_key=<key>

值得注意的是插件对密钥泄漏的防护:构造请求失败或发送失败时,错误信息中会出现的密钥会被替换为****************

redactedAPIKey := "****************" ... return fmt.Errorf("unable to create http.Request, %s", strings.ReplaceAll(err.Error(), d.Apikey, redactedAPIKey))

这保证即使url或网络错误把带密钥的 URL 带入日志,日志里也不会留下明文 key。

指标命名规则:metric + "." + field

Datadog 指标名的生成规则(与 README 一致,实现于 convertToDatadogMetric):

  • 一般地,指标名 =Telegraf 指标名 + "." + 字段名,例如指标cpu的字段usage_user会变成cpu.usage_user
  • 特例:字段名恰好是value时不再追加后缀,直接使用指标名(源码注释adding .value seems redundant here)。这与 statsd 输入产生的value字段天然契合。

标签(tags)与 host 的处理:

  • 所有 Telegraf tag 按key:value格式拼接为 Datadog tags 数组,见 buildTags 与 TestBuildTags(例如 tagone=two"one:two");
  • 名为host的 tag 被单独取出,填充到 JSON 的host字段(host, _ := m.GetTag("host")),它同时也会出现在 tags 中。

字段值与指标类型转换规则

数值类型转换:一切皆 float

Datadog v1 API 只接受浮点数值,因此 setValue 负责把 Telegraf 字段值统一转为float64

  • int64/uint64/float64:直接转换;
  • boolfalse → 0.0true → 1.0
  • 其他类型(如字符串):返回undeterminable field type错误,整个指标会被记录日志并跳过(Unable to build Metric for %s ... skipping)。

字符串在更前置的 verifyValue 就被判定为非法:

func verifyValue(v interface{}) bool { switch v := v.(type) { case string: return false case float64: // The payload will be encoded as JSON, which does not allow NaN or Inf. return !math.IsNaN(v) && !math.IsInf(v, 0) } return true }

也就是说:

  • 字符串字段被忽略(TestVerifyValue 验证"11234.5"字符串被判为无效);
  • NaN/Inf这类无法用 JSON 表示的浮点值被忽略(TestNaNIsSkipped 与 TestInfIsSkipped 验证了仅含此类字段时整个指标不会触发任何网络请求)。

buildMetrics 逐字段执行“校验 → 转 float → 填充时间戳”,时间戳取m.Time().Unix()(秒级),TestBuildPoint 覆盖了 float、int32/int64、uint64、bool 等各类输入的预期输出。

指标类型映射(type 字段)

Datadog 的type与 Telegraf 的 metric type 对应关系在 convertToDatadogMetric 中:

Telegraf 类型未设置 rate_interval设置 rate_interval 且可 rate 化
gaugegaugegauge(不转换)
countercountrate(值除以 interval,见下)
untyped空(不输出 type)rate(仅 statsd 的 count 字段)
其他

同时interval字段:默认1;被 rate 化时取rate_interval的秒数(源码注释:interval is expected to be in seconds)。

rate_interval 深入:与 Datadog Agent 对表的关键配置

README 对rate_interval的说明是:

When non-zero, converts count metrics submitted by inputs.statsd into rate, while dividing the metric value by this number. Note that in order for metrics to be submitted simultaneously alongside a Datadog agent, rate_interval has to match the interval used by the agent - which defaults to 10s

其设计目标是:让 Telegraf 可以和 Datadog Agent 并存上报同一业务指标的 rate 值(Datadog Agent 默认按10s计算 rate)。转换逻辑集中在两个函数:

转换条件——isRateable 依赖inputs.statsd写入的metric_typetag(该 tag 由 plugins/inputs/statsd/statsd.go 在解析 statsd 报文时按gauge|set|counter|timing|histogram|distribution设置):

  • metric_type = "counter":整个指标可 rate 化;
  • metric_type = "timing""histogram":只有名为count的字段可 rate 化(mean/median/sum 等统计量字段保持原样);
  • 其他情况:不转换。

这正是文档强调“只支持经由inputs.statsd摄入的指标”的原因——没有metric_typetag 就无法判定是否可 rate 化。

转换动作(datadog.go):

if d.RateInterval > 0 && isRateable(statsDMetricType, fieldName) { // interval is expected to be in seconds rateIntervalSeconds := time.Duration(d.RateInterval).Seconds() interval = int64(rateIntervalSeconds) dogM[1] = dogM[1] / rateIntervalSeconds tname = "rate" }

即值除以rate_interval的秒数、interval取该秒数、type置为rate

单元测试 TestNonZeroRateIntervalConvertsRatesToCount 与 TestZeroRateIntervalConvertsRatesToCount 提供了精确的预期值:

  • rate_interval = 10s时,counter 指标value=10010type="rate"Interval=10
  • metric_type="timing"/"histogram"时,count=10.1且指标名为<name>.count,而lower/mean/median/stddev/sum/upper等字段保持原值、type为空、Interval=1
  • rate_interval = 0(默认)时,counter 保持type="count"、原值100Interval=1,timing/histogram 的 count 字段也不转换。

因此实践建议是:只有当你需要 Telegraf 的 statsd 数据与 Datadog Agent 的 rate 曲线叠加展示时,才把rate_interval设为与 Datadog Agent 相同的 interval(通常10s);否则保持默认0s,让 counter 以count类型原值上报。

错误处理与可观测性小结

汇总该插件的失败模式,便于排障:

现象触发点源码位置
apikey is a required field for datadog output未配置 apikey,Connect 阶段Connect
error parsing proxy url ...http_proxy_url非法proxy.go
Unable to build Metric for <name> ... skipping字段类型无法转 float(如字符串混入),单条跳过并记 Info 日志convertToDatadogMetric
unable to marshal TimeSeries: ...JSON 序列化失败Write
received bad status code, <code>: <body>响应码不在 200–209,返回 Datadog 响应体原文Write
error POSTing metrics, ...(密钥已打码)网络/超时等请求失败Write

快速上手清单

  1. telegraf.conf中添加[[outputs.datadog]]并填入apikey(可参考 sample.conf);
  2. 内网环境按需配置use_system_proxy/http_proxy_url
  3. 需要压缩传输时设compression = "zlib"(请求头为Content-Encoding: deflate);
  4. url指向本地 mock(或临时抓包代理)验证负载格式与命名规则是否符合预期,再改回默认端点;
  5. 若与 Datadog Agent 并存上报 statsd 指标,设rate_interval = "10s"(须与 Agent 的 rate interval 一致)。

相关代码与测试入口:插件实现、单元测试、公共代理组件、内容压缩组件、statsd 输入的 metric_type tag 来源、插件通用配置文档。

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

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

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

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

立即咨询