Telegraf Amazon Timestream Output 插件完全指南:配置、数据映射与源码级剖析
【免费下载链接】telegrafAgent for collecting, processing, aggregating, and writing metrics, logs, and other arbitrary data.项目地址: https://gitcode.com/GitHub_Trending/te/telegraf
本篇技术指南以 Telegraf 仓库中 plugins/outputs/timestream/README.md 为骨架,结合 timestream.go 源码、sample.conf 配置样例与 timestream_test.go 单元测试,系统讲解如何将 Telegraf 采集的指标写入 AWS Amazon Timestream 时序数据库。读完本文,你将掌握该插件的完整配置项含义、四种 Influx 到 Timestream 的数据映射模式、凭据加载链、批量写入与错误重试机制,并能据此搭建可上线的监控数据落库方案。
插件概览
outputs.timestream是 Telegraf 官方提供的输出插件,负责把 Telegraf 指标(metrics)写入 AWS 的 Amazon Timestream 托管时序数据库服务。该插件自Telegraf v1.16.0起可用,属于cloud、datastore类目,支持所有平台(all)。
从源码结构看,插件在 timestream.go 中通过outputs.Add("timestream", ...)注册,并在 plugins/outputs/all/timestream.go 中完成默认构建时的导入注册。其底层基于 AWS SDK for Go v2 的timestreamwrite服务客户端,核心接口WriteClient仅封装了三个操作:CreateTable、WriteRecords与DescribeDatabase(见 timestream.go),并通过WriteFactory变量注入客户端以便单元测试替换 mock(timestream.go)。
认证机制(Authentication)
插件使用AWS 凭据链(credential chain)向 Timestream API 端点进行认证,按以下顺序尝试:
- 若同时指定
role_arn与web_identity_token_file,则通过 STS 使用Web identity provider凭据; - 若指定
role_arn,则通过 STS 使用AssumeRole 假定凭据(源凭据按后续规则依次评估)。注意:endpoint_url只作用于 Timestream 服务本身,拉取凭据时一律使用 STS 全局端点; - 通过
access_key、secret_key、token显式指定凭据; - 通过
profile指定共享配置文件中的 profile; - 环境变量(
AWS_ACCESS_KEY_ID等); - 共享凭据文件(Shared Credentials File);
- EC2 实例角色(EC2 Instance Profile)。
源码实现印证
该凭据链在 plugins/common/aws/credentials.go 中实现:CredentialConfig.Credentials()首先判断RoleARN是否为空——非空则走configWithAssumeCredentials()(内部基于 STS 客户端创建AssumeRoleProvider或WebIdentityRoleProvider),否则走configWithRootCredentials()(依次叠加 profile、共享凭据文件、静态凭据,最后回落到 SDK 默认的环境变量/实例角色链)。Timestream 插件通过内嵌common_aws.CredentialConfig复用这套机制(timestream.go)。
配置详解
以下为完整配置样例(与 sample.conf 一致),随后逐项说明:
# Configuration for sending metrics to Amazon Timestream. [[outputs.timestream]] ## Amazon Region region = "us-east-1" ## Amazon Credentials ## Credentials are loaded in the following order: ## 1) Web identity provider credentials via STS if role_arn and ## web_identity_token_file are specified ## 2) Assumed credentials via STS if role_arn is specified ## 3) explicit credentials from 'access_key' and 'secret_key' ## 4) shared profile from 'profile' ## 5) environment variables ## 6) shared credentials file ## 7) EC2 Instance Profile #access_key = "" #secret_key = "" #token = "" #role_arn = "" #web_identity_token_file = "" #role_session_name = "" #profile = "" #shared_credential_file = "" ## Endpoint to make request against, the correct endpoint is automatically ## determined and this option should only be set if you wish to override the ## default. ## ex: endpoint_url = "http://localhost:8000" # endpoint_url = "" ## Timestream database where the metrics will be inserted. ## The database must exist prior to starting Telegraf. database_name = "yourDatabaseNameHere" ## Specifies if the plugin should describe the Timestream database upon ## starting to validate if it has access, necessary permissions, connection, ## etc., as a safety check. If the describe operation fails, the plugin will ## not start and therefore the Telegraf agent will not start. describe_database_on_start = false ## Specifies how the data is organized in Timestream. ## Valid values are: single-table, multi-table. ## When mapping_mode is set to single-table, all of the data is stored in a ## single table. When mapping_mode is set to multi-table, the data is ## organized and stored in multiple tables. The default is multi-table. mapping_mode = "multi-table" ## Specifies if the plugin should create the table, if it doesn't exist. create_table_if_not_exists = true ## Specifies the Timestream table magnetic store retention period in days. ## Check Timestream documentation for more details. ## NOTE: This property is valid when create_table_if_not_exists = true. create_table_magnetic_store_retention_period_in_days = 365 ## Specifies the Timestream table memory store retention period in hours. ## Check Timestream documentation for more details. ## NOTE: This property is valid when create_table_if_not_exists = true. create_table_memory_store_retention_period_in_hours = 24 ## Specifies how the data is written into Timestream. ## Valid values are: true, false ## When use_multi_measure_records is set to true, all of the tags and fields ## are stored as a single row in a Timestream table. ## When use_multi_measure_record is set to false, Timestream stores each field ## in a separate table row, thereby storing the tags multiple times (once for ## each field). The recommended setting is true. The default is false. use_multi_measure_records = "false" ## Specifies the measure_name to use when sending multi-measure records. ## NOTE: This property is valid when use_multi_measure_records=true and ## mapping_mode=multi-table measure_name_for_multi_measure_records = "telegraf_measure" ## Specifies the name of the table to write data into ## NOTE: This property is valid when mapping_mode=single-table. # single_table_name = "" ## Specifies the name of dimension when all of the data is being stored in a ## single table and the measurement name is transformed into the dimension ## value (see Mapping data from Influx to Timestream for details) ## NOTE: This property is valid when mapping_mode=single-table. # single_table_dimension_name_for_telegraf_measurement_name = "namespace" ## Only valid and optional if create_table_if_not_exists = true ## Specifies the Timestream table tags. ## Check Timestream documentation for more details # create_table_tags = { "foo" = "bar", "environment" = "dev"} ## Specify the maximum number of parallel go routines to ingest/write data ## If not specified, defaulted to 1 go routines max_write_go_routines = 25参数逐项说明
| 配置项 | 类型/取值 | 默认值 | 说明 |
|---|---|---|---|
region | 字符串 | 必填 | AWS 区域,例如us-east-1。 |
access_key/secret_key/token | 字符串 | 空 | 显式静态凭据,优先级低于 STS 假定凭据。 |
role_arn | 字符串 | 空 | 通过 STS AssumeRole 获取临时凭据;若同时配置web_identity_token_file则使用 Web Identity 方式。 |
web_identity_token_file | 字符串 | 空 | Web identity token 文件路径,与role_arn搭配使用(如 EKS IRSA 场景)。 |
role_session_name | 字符串 | 空 | AssumeRole 会话名,便于在 CloudTrail 中溯源。 |
profile | 字符串 | 空 | 指定共享凭据文件(~/.aws/credentials)中的 profile 名。 |
shared_credential_file | 字符串 | 空 | 自定义共享凭据文件路径。 |
endpoint_url | 字符串 | 空 | 覆盖 Timestream 服务端点,仅在你需要指向自定义/本地模拟端点(如http://localhost:8000)时设置。从 credentials.go 可确认其仅作用于 Timestream 客户端,不影响 STS。 |
database_name | 字符串 | 必填 | 目标数据库名,该数据库必须在启动 Telegraf 之前已存在。 |
describe_database_on_start | bool | false | 启动时调用DescribeDatabase校验权限、连通性等;若该操作失败,插件不会启动,Telegraf agent 也随之启动失败。 |
mapping_mode | single-table/multi-table | multi-table | 数据组织方式,详见下文映射模式。 |
create_table_if_not_exists | bool | true | 表不存在时是否自动建表。 |
create_table_magnetic_store_retention_period_in_days | int64 | 365 | 磁存储(Magnetic Store)保留天数,仅当create_table_if_not_exists=true时生效。 |
create_table_memory_store_retention_period_in_hours | int64 | 24 | 内存存储(Memory Store)保留小时数,仅当create_table_if_not_exists=true时生效。 |
use_multi_measure_records | bool | false | true时一条 Telegraf 指标的所有 tag 与 field 以单行 Multi-Measure 记录写入;false时每个 field 单独占一行(tag 随之重复存储)。官方推荐设为true。 |
measure_name_for_multi_measure_records | 字符串 | telegraf_measure | 仅当use_multi_measure_records=true且mapping_mode=multi-table时有效,指定 Multi-Measure 记录的 measure_name。 |
single_table_name | 字符串 | 空 | 仅mapping_mode=single-table时有效,指定写入的单表表名。 |
single_table_dimension_name_for_telegraf_measurement_name | 字符串 | namespace | 仅mapping_mode=single-table时有效,指定存放 measurement 名的维度名(measurement 名会转换为该维度的值)。 |
create_table_tags | map[string]string | 空 | 仅当create_table_if_not_exists=true时可选,指定建表时的表标签,如{ "foo" = "bar", "environment" = "dev"}。 |
max_write_go_routines | int | 1 | 并发写数据的 Go 协程数上限。源码常量maxWriteRoutinesDefault = 1(timestream.go)表明未配置时默认 1。 |
配置校验规则(源码视角)
在Connect()中(timestream.go),插件会执行严格的参数校验,测试用例TestConnectValidatesConfigParameters(timestream_test.go)覆盖了这些约束:
database_name与mapping_mode为必填项,缺失直接报错;mapping_mode仅允许single-table与multi-table两个取值;- single-table 模式下必须配置
single_table_name;当use_multi_measure_records=false时还必须配置single_table_dimension_name_for_telegraf_measurement_name(measurement 名需要有个维度去承载);此时若又配置了measure_name_for_multi_measure_records则报错(因为单表 + 多测点场景下,measurement 名直接充当 multi-measure 名); - multi-table 模式下禁止配置
single_table_name与single_table_dimension_name_for_telegraf_measurement_name;当use_multi_measure_records=true时必须配置measure_name_for_multi_measure_records; - 若
create_table_if_not_exists=true,两个保留期参数都必须大于 0; max_write_go_routines <= 0时回落到默认值 1。
字段类型与 Unsigned Integers 处理
Timestream不支持无符号 64 位整型(unsigned int64)。convertValue()(timestream.go)的类型转换规则如下:
| Telegraf 字段类型 | Timestream MeasureValueType | 说明 |
|---|---|---|
int,int8,int16,int32,int64 | BIGINT | 直接转十进制字符串。 |
uint,uint8,uint16,uint32 | BIGINT | 直接转十进制字符串。 |
uint64 | BIGINT | 若值<= math.MaxInt64原样输出;超过最大有符号 int64 的值会被截断(capped)为9223372036854775807。 |
float32,float64 | DOUBLE | 使用FormatFloat(..., 'f', -1, ...)输出。 |
bool | BOOLEAN | 输出"true"/"false"。 |
string | VARCHAR | 直接输出。 |
| 其他类型 | — | 被跳过(ok=false),详见"错误处理"一节。 |
测试TestBuildMultiMeasuresInSingleAndMultiTableMode(timestream_test.go)专门验证了uint64(math.MaxUint64)被转换为"9223372036854775807"的行为。
批量写入(Batching)与并发(Multithreading)
CommonAttributes 批量优化
插件利用 TimestreamWriteRecordsInput.CommonAttributes高效批量写入。核心逻辑在TransformMetrics()(timestream.go):
- 每条 Telegraf 指标按表名(tableName)分组聚合——single-table 模式统一落到
single_table_name,multi-table 模式以 measurement 名作为表名; - 由于 Telegraf 指标已被 metric 的序列化逻辑按 Name、Tag Keys、Time 归一化,相同表下的记录可以共享
CommonAttributes(空 Record 占位,维度与时间放在单条 Record 上),从而压缩请求体; - 针对Timestream WriteRecords API 单次调用 100 条记录的上限(源码常量
maxRecordsPerCall = 100,timestream.go),partitionRecords()会将超出上限的请求自动拆分为多个不超过 100 条的WriteRecordsInput。
测试TestTransformMetricsRequestsAboveLimitAreSplit(timestream_test.go)验证了 101 条记录会被拆成 100 + 1 两个请求;TestWriteMultiMeasuresSingleTableMode验证了 101 条多测点记录产生 2 次WriteRecords调用。
多线程写入
README 中说明"默认单线程写入",但从源码看,Write()(timestream.go)会根据max_write_go_routines启动至多 N 个 worker 协程并发消费写任务 channel(任务数少于协程数时取小者)。MaxWriteGoRoutinesCount <= 0时回落默认 1,即经典的单协程行为。每个 worker 调用writeToTimestream()执行实际的WriteRecords。
错误处理与重试语义(Errors)
writeToTimestream()(timestream.go)按 AWS 异常类型区分处理策略,这是理解"数据会不会丢"的关键:
- 字段类型不受支持:该字段被丢弃,错误写入日志。例如
TestTransformMetricsUnsupportedFieldsAreSkipped中time.Time类型的 field 被跳过(timestream_test.go); - ThrottlingException 或 InternalServerException(5xx):错误返回给 Telegraf,Telegraf 会把这些指标保留在输出缓冲区中,在下一个 flush 周期自动重试写入。测试
TestThrottlingErrorIsReturnedToTelegraf验证了这一行为(timestream_test.go); - ResourceNotFoundException(表不存在):
- 若
create_table_if_not_exists=true:插件先尝试建表(createTableAndRetry(),timestream.go),建表成功则重写一次记录;建表失败则记录错误并跳过; - 若
create_table_if_not_exists=false:记录被丢弃并输出错误日志;
- 若
- RejectedRecordsException:逐条输出被拒绝记录的原因与索引(
reject reason/record index),整批记录不重试(重试无意义),返回nil避免 Telegraf 反复重试。测试TestRejectedRecordsErrorResultsInMetricsBeingSkipped验证该行为(timestream_test.go); - 其他 AWS 错误(OperationError):记录被丢弃并记录日志,因为重试这类请求基本不会成功;
- 非 AWS 网络错误:作为可重试错误返回给 Telegraf。
建表本身(createTable(),timestream.go)会携带两个保留期配置并打上create_table_tags;若遇到ConflictException(并发下别人已建表)则视为成功。
日志与调试(Logging)
开启 Telegraf 的debug 标志可输出详细日志,包括正在写入 Timestream 的记录内容。源码中的日志点包括:
Constructing Timestream client for "multi-table" mode(客户端构建);Describing database "..." in region "..."与 Describe 结果(仅describe_database_on_start=true时);WriteToTimestream - Metrics size: N request size: M time(ms): T(每次 flush 的指标数、请求数与耗时统计);- 各类错误日志统一带数据库名与表名,便于定位。
单元测试(Testing)
插件附带完整单元测试,在插件目录下执行:
go test -v ./plugins/outputs/timestream/...测试文件 timestream_test.go 通过覆盖全局WriteFactory注入 mock 客户端(mockTimestreamClient/mockTimestreamErrorClient),无需真实 AWS 环境即可验证:
- 配置校验(
TestConnectValidatesConfigParameters); - 多测点记录在单表/多表模式下的生成与写入次数(
TestWriteMultiMeasuresSingleTableMode、TestWriteMultiMeasuresMultiTableMode); - 超过 100 条上限的请求拆分(
TestTransformMetricsRequestsAboveLimitAreSplit); - 不同维度、不同时间戳、不同 measurement 的分组写入策略(
TestTransformMetricsSameDimensionsSameTimestampsAreWrittenTogether、TestTransformMetricsSameDimensionsDifferentTimestampsAreWrittenSeparate、TestTransformMetricsDifferentMetricsAreWrittenToDifferentTablesInMultiTableMapping等); - 错误类型对应的重试/丢弃语义(
TestThrottlingErrorIsReturnedToTelegraf、TestRejectedRecordsErrorResultsInMetricsBeingSkipped); - 自定义端点(
TestCustomEndpoint)。
从 Influx 到 Timestream 的数据映射(Mapping)
默认情况下,Telegraf 的 Influx 行协议数据映射到 Timestream 遵循四条规则:
- 时间戳→ Timestream 的
time字段; - Tags→ Timestream 的dimensions(维度);
- Fields→ Timestream 的measures(度量);
- Measurement 名→ Timestream 的表名。
时间戳换算由getTimestreamTime()(timestream.go)实现:它会自动选择能无损表达该时间戳的最小粒度TimeUnit——整秒用SECONDS、整毫秒用MILLISECONDS、整微秒用MICROSECONDS,否则用NANOSECONDS,从而兼顾精度与存储开销。
下面以两行 Influx 行协议数据为例,完整演示四种映射模式:
weather,location=us-midwest,season=summer temperature=82,humidity=71 1465839830100400200 airquality,location=us-west no2=5,pm25=16 1465839830100400200其中weather、airquality是 measurement 名;location、season是 tag;temperature、humidity、no2、pm25是 field。
模式一:multi-table + use_multi_measure_records=true(每 measurement 一张表,每行多字段)
- 插件创建
weather、airquality两张表(mapping_mode=multi-table); - 每行包含该指标的多个字段(
use_multi_measure_records=true); - 表
weather内容如下(<measure_name_for_multi_measure_records>即该配置项的实际值):
| time | location | season | measure_name | temperature | humidity |
|---|---|---|---|---|---|
| 2016-06-13 17:43:50 | us-midwest | summer | <measure_name_for_multi_measure_records> | 82 | 71 |
- 表
airquality内容如下:
| time | location | measure_name | no2 | pm25 |
|---|---|---|---|---|
| 2016-06-13 17:43:50 | us-west | <measure_name_for_multi_measure_records> | 5 | 16 |
模式二:multi-table + use_multi_measure_records=false(每 measurement 一张表,每字段一行)
- 插件创建
weather、airquality两张表(mapping_mode=multi-table); - 每个字段单独占一行(
use_multi_measure_records=false); - 表
weather内容如下:
| time | location | season | measure_name | measure_value::bigint |
|---|---|---|---|---|
| 2016-06-13 17:43:50 | us-midwest | summer | temperature | 82 |
| 2016-06-13 17:43:50 | us-midwest | summer | humidity | 71 |
- 表
airquality内容如下:
| time | location | measure_name | measure_value::bigint |
|---|---|---|---|
| 2016-06-13 17:43:50 | us-west | no2 | 5 |
| 2016-06-13 17:43:50 | us-west | pm25 | 16 |
模式三:single-table + use_multi_measure_records=true(单表,每行多字段)
- 插件创建名为
<single_table_name>的一张表(mapping_mode=single-table); - 每行包含多个字段(
use_multi_measure_records=true); - measurement 名作为
<single_table_dimension_name_for_telegraf_measurement_name>维度的值写入:
| time | location | season | <single_table_dimension_name_for_telegraf_measurement_name> | measure_name | temperature | humidity | no2 | pm25 |
|---|---|---|---|---|---|---|---|---|
| 2016-06-13 17:43:50 | us-midwest | summer | weather | <measure_name_for_multi_measure_records> | 82 | 71 | null | null |
| 2016-06-13 17:43:50 | us-west | null | airquality | <measure_name_for_multi_measure_records> | null | null | 5 | 16 |
注意:此模式下源码会忽略配置的
measure_name_for_multi_measure_records,而直接使用 measurement 名作为 multi-measure 名(见 timestream.go 与TestBuildMultiMeasuresInSingleAndMultiTableMode中 single-table 分支的断言)。
模式四:single-table + use_multi_measure_records=false(单表,每字段一行)
- 插件创建名为
<single_table_name>的一张表(mapping_mode=single-table); - 每个字段单独占一行(
use_multi_measure_records=false); - 表内容如下(以
namespace作为承载 measurement 名的维度为例):
| time | location | season | namespace | measure_name | measure_value::bigint |
|---|---|---|---|---|---|
| 2016-06-13 17:43:50 | us-midwest | summer | weather | temperature | 82 |
| 2016-06-13 17:43:50 | us-midwest | summer | weather | humidity | 71 |
| 2016-06-13 17:43:50 | us-west | NULL | airquality | no2 | 5 |
| 2016-06-13 17:43:50 | us-west | NULL | airquality | pm25 | 16 |
上表中
<single_table_name>、<single_table_dimension_name_for_telegraf_measurement_name>、<measure_name_for_multi_measure_records>均代表对应配置项的实际取值。
如何选择映射模式
- 多表模式天然贴合 Influx 的 measurement → 表 语义,查询隔离性好,适合 measurement 集合固定、且希望按业务分表管理的场景;
- 单表模式将所有数据聚合到一张表,配合
single_table_dimension_name_for_telegraf_measurement_name维度区分来源,适合表数量敏感、希望统一管理保留策略与权限的场景; - **Multi-Measure 记录(推荐)**能显著减少行数、压缩维度重复存储开销,适合字段较多的高频指标。
通用配置与运行约束
该插件同样支持 Telegraf 输出插件的通用配置能力(metric 过滤、tag/field 改名、别名、插件顺序等),详见 CONFIGURATION.md 与 plugins 通用文档。
几点上线前必须确认的前提:
- 数据库需预先创建:
database_name指向的数据库必须在启动前存在,表可由插件自动创建(create_table_if_not_exists=true),数据库则不能; - IAM 权限:插件运行需要
timestream:DescribeDatabase、timestream:WriteRecords、timestream:CreateTable(后者仅自动建表时需要)等权限,具体以 AWS IAM 策略为准; - 保留期参数:仅当
create_table_if_not_exists=true且需要自动建表时才必须大于 0,且均需符合 Timestream 服务的取值约束; - 写入失败重试:只有 Throttling / 5xx 类可重试错误会触发 Telegraf 缓冲重试,其余错误(如字段类型非法、RejectedRecords)会被丢弃并记日志,因此建议开启 debug 日志观察写入健康度。
【免费下载链接】telegrafAgent for collecting, processing, aggregating, and writing metrics, logs, and other arbitrary data.项目地址: https://gitcode.com/GitHub_Trending/te/telegraf
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考