Telegraf Prometheus Serializer 实战指南:将指标序列化为 Prometheus 文本格式
2026/9/15 12:00:19 网站建设 项目流程

Telegraf Prometheus Serializer 实战指南:将指标序列化为 Prometheus 文本格式

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

Prometheus 文本暴露格式(Text Exposition Format)是监控生态中最通用的指标交换格式之一。本文聚焦 Telegraf 内置的prometheus数据格式序列化器,讲解其核心配置、字段到样本的映射规则、名称净化机制、Histogram/Summary 类型支持,以及如何与prometheus输入插件配合实现指标无损往返(round-trip)。读完本文,你将能够在任意支持data_format的输出插件中正确配置并产出标准的 Prometheus 文本输出。

概述:prometheus 序列化器的定位

Telegraf 支持大量输出插件,而data_format机制允许你在输出侧统一选择序列化格式。prometheus序列化器就是其中之一,它把 Telegraf 内部的度量(Metric)转换成 Prometheus 文本暴露格式(见 输出数据格式总览)。它通常用于:

  • 通过file输出插件落盘或打印 Prometheus 格式的指标;
  • 通过 HTTP 类输出向 Prometheus 生态的采集端暴露指标;
  • prometheus输入插件配对,实现指标采集→处理→再输出的闭环。

文档特别强调:当配合prometheus输入插件使用时,输入侧应启用metric_version = 2选项,才能保证指标类型信息正确往返(该选项定义见 prometheus 输入插件)。

完整配置示例

以下配置将序列化结果打印到标准输出,并开启批量格式(batch format):

[[outputs.file]] files = ["stdout"] use_batch_format = true ## Include the metric timestamp on each sample. prometheus_export_timestamp = false ## Sort prometheus metric families and metric samples. Useful for ## debugging. prometheus_sort_metrics = false ## Output string fields as metric labels; when false string fields are ## discarded. prometheus_string_as_label = false ## Encode metrics without HELP metadata. This helps reduce the payload ## size. prometheus_compact_encoding = false ## Control how metric names and label names are sanitized. ## The default "legacy" keeps ASCII-only Prometheus name rules. ## Set to "utf8" to allow UTF-8 metric and label names. ## Valid options: "legacy", "utf8" prometheus_name_sanitization = "legacy" ## Data format to output. ## Each data format has its own unique set of configuration options, read ## more about them here: ## docs/DATA_FORMATS_INPUT.md data_format = "prometheus" ## Specify the metric type explicitly. ## This overrides the metric-type of the Telegraf metric. Globbing is allowed. [outputs.file.prometheus_metric_types] counter = [] gauge = []

配置项详解

prometheus序列化器的所有配置项都在结构体FormatConfig中定义,位于 prometheus.go,并注册在serializers注册表中(serializers.Add("prometheus", ...))。下面逐一说明:

配置项TOML 键默认值作用
prometheus_export_timestampExportTimestampfalse是否在每个样本上附带指标时间戳(毫秒精度)。
prometheus_sort_metricsSortMetricsfalse是否对 metric family 与样本排序,便于调试时输出稳定。
prometheus_string_as_labelStringAsLabelfalse是否把字符串字段输出为标签;为false时字符串字段直接丢弃。
prometheus_compact_encodingCompactEncodingfalse是否省略 HELP 元数据行,缩小输出体积。
prometheus_name_sanitizationNameSanitization"legacy"指标名与标签名的净化策略,可选"legacy""utf8"
prometheus_metric_typesTypeMappings通过 glob 显式指定指标类型,覆盖 Telegraf 自带类型。

Init()方法中,序列化器会校验prometheus_name_sanitization的值:空值回退为"legacy""legacy""utf8"为合法值,其余取值(如"gzip")会直接报错invalid prometheus_name_sanitization,这一行为有单元测试覆盖(见 prometheus_test.go)。

字段到 Prometheus 样本的映射规则

序列化的核心逻辑位于 collection.go 的Collection.Add方法。规则如下:

  1. 每个数值字段产生一个样本:每个整数、浮点数、布尔或无符号整数字段都会生成一个 Prometheus 样本;布尔值true转换为1.0false转换为0.0。数值转换函数见 convert.go。
  2. 指标名 = measurement + "_" + field key:例如 measurement 为cpu、字段为time_idle,得到cpu_time_idle
  3. 特殊 case:当 measurement 名恰好是prometheus时,它不参与指标名拼接,直接使用字段名。这保证了从prometheus输入采集到的指标(measurement 固定为prometheus)在序列化时能还原原始名称,相关逻辑见 convert.go。
  4. 每个 tag 生成一个标签:标签名来自 tag 键,标签值来自 tag 值。
  5. 字符串字段默认被忽略:在prometheus_string_as_label = false时,字符串字段不会产生任何 Prometheus 指标(测试用例 "discard strings" 验证了该行为)。

完整示例:输入与输出

示例输入(InfluxDB line protocol):

cpu,cpu=cpu0 time_guest=8022.6,time_system=26145.98,time_user=92512.89 1574317740000000000 cpu,cpu=cpu1 time_guest=8097.88,time_system=25223.35,time_user=96519.58 1574317740000000000 cpu,cpu=cpu2 time_guest=7386.28,time_system=24870.37,time_user=95631.59 1574317740000000000 cpu,cpu=cpu3 time_guest=7434.19,time_system=24843.71,time_user=93753.88 1574317740000000000

示例输出(Prometheus 文本格式):

# HELP cpu_time_guest Telegraf collected metric # TYPE cpu_time_guest counter cpu_time_guest{cpu="cpu0"} 9582.54 cpu_time_guest{cpu="cpu1"} 9660.88 cpu_time_guest{cpu="cpu2"} 8946.45 cpu_time_guest{cpu="cpu3"} 9002.31 # HELP cpu_time_system Telegraf collected metric # TYPE cpu_time_system counter cpu_time_system{cpu="cpu0"} 28675.47 cpu_time_system{cpu="cpu1"} 27779.34 cpu_time_system{cpu="cpu2"} 27406.18 cpu_time_system{cpu="cpu3"} 27404.97 # HELP cpu_time_user Telegraf collected metric # TYPE cpu_time_user counter cpu_time_user{cpu="cpu0"} 99551.84 cpu_time_user{cpu="cpu1"} 103468.52 cpu_time_user{cpu="cpu2"} 102591.45 cpu_time_user{cpu="cpu3"} 100717.05

注意:cpu输入产生的字段被标记为 counter 类型,因此输出的# TYPE行为 counter。字段值为time_guest等的数值型字段一一对应输出;带cpu="cpu0"等标签的样本保留了 tag 信息。

名称净化:legacy 与 utf8 两种模式

Prometheus 对指标名与标签名有严格的字符约束。序列化器在输出前会对名称做净化(sanitize),逻辑见 convert.go:

  • legacy 模式(默认):指标名首字符只允许a-zA-Z:_,后续字符允许a-zA-Z0-9:_;标签名首字符只允许a-zA-Z_,后续允许a-zA-Z0-9_。不合法的 rune 会被替换为下划线,连续下划线会被压缩并去除首尾下划线;若净化后名称为空,该指标/标签会被丢弃。
  • utf8 模式:允许 UTF-8 字符出现在指标名与标签名中,适用于需要保留中文等非 ASCII 名称的场景;但对非 UTF-8 的非法输入仍会回退到 legacy 净化规则。

这些行为在 collection_test.go 中有详尽的单元测试:legacy模式下纯 UTF-8 名称(如温度-指标)净化后为空而被丢弃;utf8模式下则原样保留为温度-指标_数值-值与标签主机-名;非法字节(如0xff)在两种模式下都会回退处理。

另外,指标名中的冒号(:)是合法字符且不会被替换(见cpu::xyzzy_time_idle测试用例),而标签名中的冒号会被替换为下划线(host:namehost_name)。

类型系统:untyped、counter、gauge 与显式类型覆盖

序列化时,Telegraf 指标的类型会映射到 Prometheus 的 metric family 类型,映射函数见 convert.go:

Telegraf 类型Prometheus 类型
Countercounter
Gaugegauge
Summarysummary
Histogramhistogram
Untypeduntyped(其他类型默认)

许多输入插件产生的指标类型是untyped。如果你需要强制指定类型,可以使用配置节prometheus_metric_types,通过 glob 规则把匹配的指标名映射为countergauge,从而覆盖 Telegraf 指标自身的类型。该映射在 prometheus.go 中实现:MetricTypes.Init()counter/gauge数组编译为过滤器,DetermineTypeCollection.Add阶段按最终指标名匹配覆盖类型。相关测试用例 "untyped forced to counter" 与 "untyped forced to gauge" 验证了该机制(见 prometheus_test.go)。

批量序列化、时间戳与紧凑编码

use_batch_format 与 SerializeBatch

Prometheus 文本格式要求同一 metric family 内的样本聚合输出。序列化器实现了SerializeBatch(见 prometheus.go),将整批指标先收集到Collection中再统一输出。file输出插件通过use_batch_format = true启用批量模式;在批量模式下,来自不同 metric 的样本会按 metric family 归并,例如多个cpu_time_idle样本会输出为同一个 family 下的多个样本行。

批量模式下同一 sample 出现多次时,会保留时间戳更新的那个样本("newer sample" 测试用例验证了这一点)。

时间戳导出

prometheus_export_timestamp = true时,每个样本行末尾会附加毫秒级时间戳(源码中通过TimestampMs = metric.time.UnixNano() / int64(time.Millisecond)计算)。例如:

cpu_time_idle{host="example.org"} 42 1574279268000

紧凑编码

prometheus_compact_encoding = true时,输出会省略# HELP行(但保留# TYPE行),以减小 payload 体积:

# TYPE cpu_time_idle untyped cpu_time_idle{host="example.org"} 42

两种模式下的差异均有对应的测试用例(见 prometheus_test.go)。

Histogram 与 Summary 类型的处理及注意事项

支持方式

prometheus序列化器支持 histogram 与 summary 类型,但其样本是由多个字段组合而成的,需要专门的合并逻辑(见 collection.go):

  • Histogram<name>_bucket字段(配合letag)构成桶,<name>_sum<name>_count字段提供总和与计数;输出时指标名会去掉_bucket/_sum/_count后缀(见 convert.go)。同一边界(bound)的桶会合并更新。
  • Summary<name>_sum/<name>_count字段提供总和与计数,其余字段配合quantiletag 构成分位数样本。

完整的多桶 histogram 与多分位数 summary 序列化输出示例,可参考 prometheus_test.go。

跨批次的历史遗留问题(重要警告)

文档明确警告:当生成 histogram 与 summary 类型时,如果指标跨越多个批次,输出可能不正确。这是因为序列化器内部维护了一个Collection缓存(entries map[metricFamily]entry,每个 entry 内以metricKey索引promMetric),它通过Collection.Add累积样本,并通过Expire(now, age)按添加时间(addTime)清理过期数据(见 collection.go)。

Histogram 和 Summary 的过期时间基于最近一次收到的数据更新:只要某个桶或某个分位数持续更新,整个 metric 就会持续存活;反过来,如果某些桶/分位数停止更新而其他仍上报,则停止更新的桶/分位数会一直保留,不会自动消失。这些行为在 collection_test.go 中有系统性的测试,包括 "update metric expiration"、"histogram bucket updates"、"entire histogram expires"、"summary does not expire because of quantile addtime" 等用例。

文档的建议是:使用 histogram 与 summary 类型时,推荐只使用prometheus_client输出插件(即专为 Prometheus 设计的输出插件),因为该插件按批次采集的语义更适合这类累积型指标;若必须使用其他输出,则尽量启用支持批量写格式(batch format)的输出,以缓解但不完全消除该问题。

与 prometheus 输入的往返(round-trip)配置

如果你用prometheus输入插件采集指标,再通过本序列化器输出,请务必在输入侧设置metric_version = 2

[[inputs.prometheus]] urls = ["http://example.org/metrics"] metric_version = 2

metric_version = 2会保留 Prometheus 指标的类型信息(counter/gauge/histogram/summary),使其以 Telegraf 度量进入流水线后,经本序列化器输出时能够还原为正确的 Prometheus 类型与结构,实现无损往返。该选项的详细说明见 prometheus 输入插件文档。

深入阅读指引

如果想继续研究实现细节,建议阅读以下源码与测试文件:

  • prometheus.go:配置结构体FormatConfig、类型映射MetricTypesInit校验、Serialize/SerializeBatch入口;
  • convert.go:指标名/标签名净化、measurement+field 拼接、数值与计数/求和转换;
  • collection.go:Collection缓存、Add合并、Expire过期清理、GetProto输出 dto.MetricFamily;
  • prometheus_test.go:单条与批量序列化的完整输入输出对照;
  • collection_test.go:过期机制、histogram/summary 合并、UTF-8 名称净化等边界行为;
  • 输入插件文档:metric_version的语义与往返配置说明。

整体序列化框架及与其他格式(InfluxDB、JSON、Graphite、Prometheus Remote Write 等)的并列关系,可参考 输出数据格式总览。

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

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

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

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

立即咨询