OpenTSDB 输出插件详解:Telegraf 指标写入 Telnet 与 HTTP 双通道实战指南
【免费下载链接】telegrafAgent for collecting, processing, aggregating, and writing metrics, logs, and other arbitrary data.项目地址: https://gitcode.com/GitHub_Trending/te/telegraf
导读
OpenTSDB 输出插件是 Telegraf 内置的时序数据输出插件之一,负责将采集到的指标写入 OpenTSDB 实例,支持 Telnet 与 HTTP 两种传输协议(HTTP API 自 OpenTSDB 2.0 起被官方推荐)。读完本文,你将掌握该插件的完整配置参数语义、两种协议的底层实现原理、指标名与标签的清洗规则、批量发送与调试手段,并能够针对自建 OpenTSDB 或反向代理场景快速落地一套可运行的写入方案。
一、插件定位与适用场景
该插件在plugins/outputs目录下注册,属于输出端(datastore 类别),支持全平台运行(💻 all),自 Telegraf v0.1.9 起即已提供。其核心能力是:
- 把 Telegraf 采集到的指标(measurement + field)映射为 OpenTSDB 数据点;
- 支持Telnet API(TCP 直连、行协议写入)与HTTP API(JSON + gzip、批量 POST)两种模式;
- 通过
host参数的 URL scheme 自动选择协议:tcp://或裸主机名走 Telnet,http:///https://走 HTTP API。
从插件注册源码可见,init()中通过outputs.Add("opentsdb", ...)注册,并设置了两个默认值:HTTPPath = "/api/put"、Separator = "_"(见 opentsdb.go)。因此即使配置中省略这两项,插件也能以合理的默认行为运行。
二、完整配置与参数解析
2.1 最小可用配置
[[outputs.opentsdb]] host = "opentsdb.example.com" port = 4242当host不带 scheme 时,Connect()会自动为其补上tcp://前缀(见 opentsdb.go),因此默认走 Telnet 协议。
2.2 全部配置项详解
以下是插件官方示例配置(与 sample.conf 完全一致):
# Configuration for OpenTSDB server to send metrics to [[outputs.opentsdb]] ## prefix for metrics keys prefix = "my.specific.prefix." ## DNS name of the OpenTSDB server ## Using "opentsdb.example.com" or "tcp://opentsdb.example.com" will use the ## telnet API. "http://opentsdb.example.com" will use the Http API. host = "opentsdb.example.com" ## Port of the OpenTSDB server port = 4242 ## Number of data points to send to OpenTSDB in Http requests. ## Not used with telnet API. http_batch_size = 50 ## URI Path for Http requests to OpenTSDB. ## Used in cases where OpenTSDB is located behind a reverse proxy. http_path = "/api/put" ## Debug true - Prints OpenTSDB communication debug = false ## Separator separates measurement name from field separator = "_"各参数含义与实现细节如下:
| 配置项 | 默认值 | 作用与实现说明 |
|---|---|---|
prefix | 空 | 指标键前缀,最终 metric 名形如prefix.measurement.field;典型用途是划分命名空间便于后续按子集查询 |
host | 必填 | OpenTSDB 主机名;无 scheme 或tcp://走 Telnet,http:///https://走 HTTP API。Write()依据url.Parse得到的 scheme 分支调用WriteTelnet或WriteHTTP,遇到其它 scheme 会返回 "unknown scheme in host parameter"(见 opentsdb.go) |
port | 必填 | 服务端口,Telnet 与 HTTP 模式都会拼接为host:port使用 |
http_batch_size | 0(见下) | HTTP 模式下每次请求最多携带的数据点数量,达到该数量即触发一次 flush;Telnet 模式不使用此参数 |
http_path | /api/put | HTTP 请求的 URI 路径,反向代理后部署 OpenTSDB 时改为代理前缀 |
debug | false | 为true时打印与 OpenTSDB 的完整通信内容(详见第五节) |
separator | _ | 拼接 measurement 名与 field 名的分隔符,即最终键为prefix + measurement + separator + field |
需要说明的是http_batch_size的默认行为:若未显式配置,sendDataPoint在metricCounter == BatchSize时才会触发 flush,而该值默认 0 会导致每个点独立成批后由Write末尾的flush()一次性发送;官方示例建议配置为50,这与 opentsdb_test.go 中基准测试使用的 batch size 一致。
2.3 全局配置选项
与其他 Telegraf 插件一样,[[outputs.opentsdb]]也支持用于修改指标、标签、字段、创建别名以及配置插件执行顺序的全局配置项,详见 docs/CONFIGURATION.md#plugins 中关于 插件级通用配置 的说明。
三、Telnet 模式:行协议写入的完整原理
3.1 协议格式
OpenTSDB Telnet 模式期望的输入格式如下:
put <metric> <timestamp> <value> <tagk1=tagv1[ tagk2=tagv2 ...tagkN=tagvN]>Telegraf 输出插件会为指标键添加可选前缀,从而支持按子集查询:
put <[prefix.]metric> <timestamp> <value> <tagk1=tagv1[ tagk2=tagv2 ...tagkN=tagvN]>3.2 真实数据样例
以下是从system、mem、io、ping等输入插件采集后写入的典型行:
put nine.telegraf.system_load1 1441910356 0.430000 dc=homeoffice host=irimame scope=green put nine.telegraf.system_load5 1441910356 0.580000 dc=homeoffice host=irimame scope=green put nine.telegraf.system_load15 1441910356 0.730000 dc=homeoffice host=irimame scope=green put nine.telegraf.system_uptime 1441910356 3655970.000000 dc=homeoffice host=irimame scope=green put nine.telegraf.system_uptime_format 1441910356 dc=homeoffice host=irimame scope=green put nine.telegraf.mem_total 1441910356 4145426432 dc=homeoffice host=irimame scope=green ... put nine.telegraf.io_write_bytes 1441910366 0 dc=homeoffice host=irimame name=vda2 scope=green put nine.telegraf.io_read_time 1441910366 0 dc=homeoffice host=irimame name=vda2 scope=green put nine.telegraf.io_write_time 1441910366 0 dc=homeoffice host=irimame name=vda2 scope=green put nine.telegraf.io_io_time 1441910366 0 dc=homeoffice host=irimame name=vda2 scope=green put nine.telegraf.ping_packets_transmitted 1441910366 dc=homeoffice host=irimame scope=green url=www.google.com put nine.telegraf.ping_packets_received 1441910366 dc=homeoffice host=irimame scope=green url=www.google.com put nine.telegraf.ping_percent_packet_loss 1441910366 0.000000 dc=homeoffice host=irimame scope=green url=www.google.com put nine.telegraf.ping_average_response_ms 1441910366 24.006000 dc=homeoffice host=irimame scope=green url=www.google.com ...注意样例中system_uptime_format、ping_packets_transmitted等行在value位置为空——对应字段值为字符串类型时被插件跳过,最终只保留该测量下的数值型字段(详见第六节)。
3.3 底层实现剖析
Telnet 写入的完整逻辑位于 opentsdb.go:
- 建立连接:每次
Write调用都会net.ResolveTCPAddr+net.DialTCP新建一条 TCP 连接,逐行写入后关闭; - 时间戳换算:
m.Time().UnixNano() / 1000000000将纳秒时间戳转为秒; - 标签排序:
ToLineFormat(cleanTags(m.Tags()))先把标签键值清洗、剔除空值,再按键名排序后拼接为k=v k=v空格分隔串——排序保证了同一指标的标签序列稳定(对应测试TestBuildTagsTelnet中{"aaa": "bbb", "one": "two"}输出为aaa=bbb one=two,见 opentsdb_test.go); - 行拼接:每行格式为
put <sanitized-name> <sec> <value> <tags>\n; - 数值格式化:
buildValue对int64、uint64、float64分别转字符串,浮点使用strconv.FormatFloat(v, 'f', 6, 64)固定 6 位小数输出(见 opentsdb.go),这解释了样例中0.430000、3655970.000000的形态。
3.4 用 Go 模拟 Telnet 读取端验证写入
无需部署真实 OpenTSDB,即可用下面这段 Go 程序模拟 Telnet 服务端监听localhost:4242,把 Telegraf 写入的每一行原样打印到标准输出,用于验证插件输出格式:
// opentsdb_telnet_mode_mock.go package main import ( "io" "log" "net" "os" ) func main() { l, err := net.Listen("tcp", "localhost:4242") if err != nil { log.Fatal(err) } defer l.Close() for { conn, err := l.Accept() if err != nil { log.Fatal(err) } go func(c net.Conn) { defer c.Close() io.Copy(os.Stdout, c) }(conn) } }运行该程序后再启动 Telegraf(将host指向localhost),即可在终端实时看到形如put ...的行协议输出。
四、HTTP 模式:JSON + gzip 批量上报
4.1 工作原理
HTTP 模式实现在 opentsdb_http.go 中,核心流程为:
- 数据点组装:每个数据点被封装为
HTTPMetric结构体,其 JSON 序列化为{"metric": "...", "timestamp": ..., "value": ..., "tags": {...}}; - 批量缓冲:
requestBody内部使用gzip.Writer压缩 +json.Encoder编码,先写[再逐点追加,点间以逗号分隔,最终闭合为]——即一个合法的 JSON 数组; - 触发发送:
sendDataPoint每接收一个点递增metricCounter,当达到http_batch_size时立即flush()发送并清零计数;Write结束前会再调用一次flush()冲刷剩余数据; - 请求构建:
POST到scheme://host:port + http_path,请求头固定携带Content-Type: application/json与Content-Encoding: gzip; - 响应处理:非 2xx 状态码下,4xx 被记录错误日志并主动丢弃该批指标以避免内存缓冲溢出,其余错误状态码直接返回 error 触发 Telegraf 重试;响应体被
io.Copy(io.Discard, ...)消费以复用 HTTP 连接。
4.2 反向代理场景
当 OpenTSDB 部署在反向代理(如 Nginx)之后时,只需调整http_path指向代理的挂载路径,例如:
[[outputs.opentsdb]] host = "http://internal-opentsdb" port = 80 http_path = "/opentsdb/api/put"4.3 特殊值与类型过滤
HTTP 与 Telnet 两种模式共享同一套字段类型过滤逻辑(见 opentsdb.go):
- 仅接受
int64、uint64、float64三种数值类型; float64为NaN或±Inf时直接跳过(JSON 无法表示这些特殊值);- 其它类型(字符串、布尔等)记录 Debug 日志后跳过。
五、debug 模式:抓取通信细节
debug = true时,HTTP 模式会额外执行:
- 请求 URL 追加
?details查询参数,让 OpenTSDB 返回详细的处理结果; - 发送前用
httputil.DumpRequestOut打印请求头,并输出未压缩的原始 body; - 接收后用
httputil.DumpResponse打印完整响应(含 body)。
调试完毕后建议关闭该选项,避免在日志中泄露敏感信息与产生大量冗余输出。Telnet 模式不受debug影响,可结合 3.4 节的模拟服务端查看写入内容。
六、指标名与标签的清洗规则
6.1 sanitize 规则
OpenTSDB 对指标名与标签值有字符限制,插件通过sanitize()(见 opentsdb.go)统一处理,规则如下:
| 输入字符 | 处理方式 |
|---|---|
@*%#$ | 替换为-(连字符) |
其它非法字符(非a-zA-Z0-9、非-_./、非 Unicode 字母) | 替换为_(下划线) |
Unicode 字母(如μnicodε_letters) | 保留 |
| 空格、emoji 等 | 替换为_ |
对应测试TestSanitize验证了这些行为:"ascii 123"→"ascii_123","@*%#$!"→"-----_","“☢”"→"___"(见 opentsdb_test.go)。
6.2 标签清洗(cleanTags)
cleanTags(见 opentsdb.go)会:
- 对标签键与标签值分别执行
sanitize; - 剔除清洗后为空字符串的标签(空值标签对 OpenTSDB 无意义且会导致写入失败)。
测试TestCleanTags覆盖了特殊字符、Unicode 字母、emoji 与空 map 等用例。
七、Connect 校验与注册机制
Connect()(见 opentsdb.go)在 Telegraf 启动时执行一次连接预检:先为无 scheme 的 host 补tcp://,随后url.Parse、ResolveTCPAddr并DialTCP建立临时连接,成功即关闭。这意味着若 OpenTSDB 地址不可达,Telegraf 会在启动阶段即报错退出,属于"快速失败"设计。
插件通过 plugins/outputs/all/opentsdb.go 在默认构建中注册;使用自定义构建(custom build)时,该文件的构建标签!custom || outputs || outputs.opentsdb允许按需裁剪插件集合。
八、可接受的指标值类型
官方文档明确指出:OpenTSDB 仅允许整数(integers)与浮点数(floats)作为数据点值。结合插件实现,具体映射为:
| Telegraf 字段类型 | 处理方式 |
|---|---|
int64 | 直接写入,十进制整数格式 |
uint64 | 直接写入,十进制整数格式 |
float64 | 写入,Telnet 模式固定 6 位小数;NaN/Inf 跳过 |
| 其它(string/bool 等) | 记录 Debug 日志并跳过该字段 |
TestWriteIntegration(见 opentsdb_test.go)中的正反例验证了 float、int、uint 可正常写入,而字符串类型 "Lorem Ipsum" 会被跳过,同时验证了带特殊字符的指标名也能通过清洗后写入。
九、实践建议汇总
- 协议选择:OpenTSDB 2.0+ 推荐 HTTP API(
host = "http://..."),单请求批量发送吞吐更高且自带 gzip 压缩;老版本或最小化部署可用 Telnet; - 合理设置
http_batch_size:建议 50~500 之间,过小增加请求次数,过大占用内存并延迟上报; - 善用
prefix:用prefix = "dc1.host."之类的前缀区分机房/业务命名空间,便于按前缀筛选数据; - 配置
debug = true排查问题:确认键名、标签与时间戳是否符合预期后再关闭; - 避免特殊字符:指标与标签中尽量使用字母、数字、
-_./,减少清洗带来的命名偏差; - 检查时间戳精度:插件统一输出秒级时间戳,跨时区场景无需额外处理。
延伸阅读
- 插件完整源码:plugins/outputs/opentsdb/opentsdb.go、plugins/outputs/opentsdb/opentsdb_http.go
- 示例配置:plugins/outputs/opentsdb/sample.conf
- 单元测试与集成测试:plugins/outputs/opentsdb/opentsdb_test.go
- 插件注册入口:plugins/outputs/all/opentsdb.go
- Telegraf 全局与插件级配置说明: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),仅供参考