
Telegraf Docker Log 输入插件基于 Docker Engine API 收集容器日志的完整实战指南【免费下载链接】telegrafAgent for collecting, processing, aggregating, and writing metrics, logs, and other arbitrary data.项目地址: https://gitcode.com/GitHub_Trending/te/telegrafDocker Log 是 Telegraf 中用于实时读取 Docker 容器 stdout/stderr 日志的输入插件它通过 Docker Engine API 直接对接 daemon 的日志流将容器日志转换为docker_log指标并纳入 Telegraf 统一的采集、处理与输出管线。本文基于 plugins/inputs/docker_log/README.md 与其源码实现完整讲解该插件的配置参数、过滤机制、底层 tail 原理、TTY 多路复用处理与状态持久化能力帮助读者在真实环境中快速、可靠地采集容器日志。插件概述该插件通过 [Docker Engine API][api] 获取运行中容器的日志输出。与直接读取宿主机上的日志文件如 docker json-file 文件、journald 日志不同它调用 Docker daemon 暴露的标准接口因此无论日志驱动如何落地存储只要 daemon 支持按流stdout/stderr回放日志Telegraf 就能以统一的方式消费。从当前仓库源码plugins/inputs/docker_log/docker_log.go看插件被注册为inputs.docker_log注册时默认设置Timeout为 5 秒func init() { inputs.Add(docker_log, func() telegraf.Input { return DockerLogs{ Timeout: config.Duration(time.Second * 5), } }) }插件属于 Telegraf 的 ServiceInput 类型实现了Start/Stop意味着它会为每一个匹配的容器启动常驻的日志追踪 goroutine持续读取增量日志。[!NOTE] 该插件仅对使用local、json-file或journald日志驱动启动的容器生效。同时请确保 Telegraf 进程对所配置的 endpoint 拥有足够权限例如读取/var/run/docker.sock或访问远程 Docker TCP/TLS 端点。引入版本⭐ Telegraf v1.12.0 标签containers, logging 平台 all配置示例与参数详解插件的完整配置模板由 plugins/inputs/docker_log/sample.conf 维护并在插件Init()中通过//go:embed sample.conf嵌入作为生成示例配置的源头。最小可用配置如下# Read logging output from the Docker engine [[inputs.docker_log]] ## Docker Endpoint ## To use TCP, set endpoint tcp://[ip]:[port] ## To use environment variables (ie, docker-machine), set endpoint ENV # endpoint unix:///var/run/docker.sock ## When true, container logs are read from the beginning; otherwise reading ## begins at the end of the log. If state-persistence is enabled for Telegraf, ## the reading continues at the last previously processed timestamp. # from_beginning false ## Timeout for Docker API calls. # timeout 5s ## Containers to include and exclude. Globs accepted. ## Note that an empty array for both will include all containers # container_name_include [] # container_name_exclude [] ## Container states to include and exclude. Globs accepted. ## When empty only containers in the running state will be captured. # container_state_include [] # container_state_exclude [] ## docker labels to include and exclude as tags. Globs accepted. ## Note that an empty array for both will include all labels as tags # docker_label_include [] # docker_label_exclude [] ## Set the source tag for the metrics to the container ID hostname, eg first 12 chars source_tag false ## Optional TLS Config # tls_ca /etc/telegraf/ca.pem # tls_cert /etc/telegraf/cert.pem # tls_key /etc/telegraf/key.pem ## Use TLS but skip chain host verification # insecure_skip_verify falseendpoint连接 Docker daemon默认值为unix:///var/run/docker.sock本机 Unix socket。源码中Init()在Endpoint为空时主动补上该默认值docker_log.go。使用 TCP 连接远程 Docker 时设置为tcp://[ip]:[port]。使用环境变量例如 docker-machine 场景时设置为ENV插件将调用client.New(client.FromEnv)从 Docker CLI 约定的环境变量如DOCKER_HOST、DOCKER_TLS_VERIFY等构造客户端docker_log.go。在非ENV分支下插件会携带 User-Agentengine-api-cli-1.0创建客户端并在配置了 TLS 时注入带有 TLS 配置的 HTTP Transportdocker_log.go。timeoutDocker API 调用超时控制所有 Docker API 调用的超时时间包括列容器、inspect 容器、读取日志流。默认5s。在源码中每次 Gather 与日志追踪期间涉及 API 调用的上下文context.WithTimeout都会使用该值。from_beginning从日志开头还是末尾开始读取false默认仅读取从插件启动时刻之后产生的新日志跳过历史日志。true从容器日志的最开始读取。若 Telegraf 启用了状态持久化state-persistence则无论该选项如何重启后都会从上次最后处理的日志时间戳继续读取避免重复消费详见下文状态持久化小节。容器名称过滤# container_name_include [] # container_name_exclude []支持 glob 通配符匹配容器名称。两者均为空数组时包含所有容器。底层由filter.NewIncludeExcludeFilter构造 include/exclude 过滤器docker_log.go容器的名称取自容器Names列表中首个不带嵌套路径的名字parseContainerName见 util.go。容器状态过滤# container_state_include [] # container_state_exclude []支持 glob 匹配容器状态。关键默认行为当 include 与 exclude 均为空时仅采集running状态的容器——源码中会显式将ContainerStateInclude置为[]string{running}docker_log.go。如需采集已退出容器的历史日志可通过 include 显式加入exited等状态。Docker label 过滤与标签注入# docker_label_include [] # docker_label_exclude []将匹配的容器 label 作为指标的额外 tag 注入。两者均为空时所有 label 都会作为 tag 注入。匹配基于 label 的 key 进行 glob 过滤docker_log.go。TLS 配置连接启用 TLS 的远程 Docker daemon 时可配置tls_caCA 证书路径tls_cert客户端证书路径tls_key客户端私钥路径insecure_skip_verify跳过证书链与主机名校验不推荐生产使用全局配置所有 Telegraf 插件还支持全局与插件级的通用配置例如指标/标签/字段修改、别名、插件执行顺序等详见 docs/CONFIGURATION.md。source tag解决容器重名的指标溯源问题当环境中存在大量同名容器时例如通过编排工具重复创建名称相同的工作负载仅凭container_name无法区分数据来源。插件提供source_tag选项解决此问题source_tag true开启后所有数据点会额外带上source标签其值为容器 ID 的前 12 个字符。这是 Docker 对未显式设置 hostname 的容器所采用的默认主机名前缀即常见的主机名形式因此既保证唯一性又贴近容器实际的主机标识。底层实现见hostnameFromIDutil.gofunc hostnameFromID(id string) string { if len(id) 12 { return id[0:12] } return id }工作流程与底层原理结合源码docker_log.go插件的核心采集流程如下列出容器Gather()调用ContainerList获取当前所有容器docker_log.go并设置纳秒级时间精度acc.SetPrecision(time.Nanosecond)。过滤与去重跳过已在追踪列表containerList中的容器然后依次应用名称过滤、状态过滤。逐个追踪对每个新容器创建一个带context.WithCancel的独立 goroutine 持续 tail 日志docker_log.gogoroutine 结束或Stop()时通过 cancel 函数终止。组装基础标签通过docker.ParseImageinternal/docker/docker.go将镜像名拆分为container_image与container_version镜像未打 tag 时版本回退为unknown。探测 TTYContainerInspect检查容器Config.Tty决定日志流是单流还是多路复用docker_log.go。请求日志流调用ContainerLogs请求参数固定为ShowStdouttrue、ShowStderrtrue、Timestampstrue、Followtruefrom_beginningfalse时通过Since参数指定从启动时间或上次记录的时间戳开始docker_log.go。逐行解析并上报按行解析时间戳与消息内容调用acc.AddFields(docker_log, ...)写入指标util.go。TTY 与非 TTY日志流的两种读取模式容器启用了 TTY只有单一的 stdout 流日志直接按行读取stream标签固定为tty。容器未启用 TTYstdout 与 stderr 在 Docker 日志协议中被多路复用插件使用stdcopy.StdCopy将复合流分离为独立的 stdout/stderr 两个管道分别 tailtailMultiplexedutil.gostream标签对应stdout或stderr。源码注释明确说明了两者的差异docker_log.go这也是 Docker 日志 API 的标准行为理解它能帮助排查日志看起来缺了一半或 stream 标签不准确的问题。日志行解析细节parseLineutil.go将每行按首个空格拆分为 RFC3339Nano 时间戳与消息体保留消息前导空格避免破坏缩进/堆栈信息同时去除行尾空白字符与 syslog 等日志插件的处理方式保持一致。若某一行时间戳解析失败会通过acc.AddError上报而不会中断整体采集。状态持久化重启后不重不漏地续读插件实现了StatefulPlugin接口GetState/SetState以容器 ID → 最后处理日志时间戳的映射作为持久化状态docker_log.go。相关机制参见 docs/developers/STATE_PERSISTENCE.md每次处理完日志行都会更新lastRecord[容器ID]为最新时间戳多个流取较晚者。Telegraf 关闭时调用GetState()汇总状态仅当agent配置节设置了statefile时才写入磁盘。下次启动时SetState()在Init()之后被调用恢复各容器的时间戳后续 tail 时通过Since参数从该时间戳继续从而避免重复采集历史日志。这也解释了配置注释中的表述开启状态持久化后读取会从上次最后处理的时间戳继续。测试用例 TestStatePersistence 与TestStatePersistenceMux分别验证了 TTY 单流与非 TTY 多路复用两种模式下的状态保存与恢复TestGatherConcurrentState则以 64 个容器并发追踪验证共享状态映射的并发安全性。指标结构与示例输出每次采集产生一条docker_log指标tagscontainer_image镜像名不含 tagcontainer_version镜像 tag无 tag 时为unknowncontainer_name容器名streamstdout、stderr或ttysource仅当source_tag true时存在取容器 ID 前 12 字符以及命中的 Docker label作为附加 tagfieldscontainer_id完整容器 IDmessage日志行内容时间戳为日志行自带的时间戳纳秒精度。示例输出如下docker_log,container_imagetelegraf,container_namesharp_bell,container_versionalpine,streamstderr container_id371ee5d3e58726112f499be62cddef800138ca72bbba635ed2015fbf475b1023,message2019-06-19T03:11:11Z I! [agent] Config: Interval:10s, Quiet:false, Hostname:\371ee5d3e587\, Flush Interval:10s 1560913872000000000 docker_log,container_imagetelegraf,container_namesharp_bell,container_versionalpine,streamstderr container_id371ee5d3e58726112f499be62cddef800138ca72bbba635ed2015fbf475b1023,message2019-06-19T03:11:11Z I! Tags enabled: host371ee5d3e587 1560913872000000000 docker_log,container_imagetelegraf,container_namesharp_bell,container_versionalpine,streamstderr container_id371ee5d3e58726112f499be62cddef800138ca72bbba635ed2015fbf475b1023,message2019-06-19T03:11:11Z I! Loaded outputs: file 1560913872000000000测试与验证仓库中的测试docker_log_test.go通过 mock Docker daemon 覆盖了核心行为可作配置与排查参考TestGather验证无容器、TTY 单流容器、非 TTY 多路复用容器三种场景下的指标结构与内容。TestGatherConcurrentState64 个容器并发追踪校验并发安全。TestStatePersistence/TestStatePersistenceMux验证停止插件后状态被正确记录、恢复后从断点续读。实战要点小结确认容器使用local、json-file或journald日志驱动并保证 Telegraf 对 endpoint 有访问权限本机通常需要 telegraf 用户加入docker组或调整 socket 权限。默认只采集running状态容器需要采集历史日志时设置from_beginning true并配合状态持久化使用。容器重名频繁时开启source_tag true利用容器 ID 前 12 位唯一标识数据来源。通过container_name_include/exclude、docker_label_include/exclude控制采集范围与标签维度避免无关容器日志与标签爆炸。远程连接务必配置好 TLS 参数对 docker-machine 等环境可直接使用endpoint ENV。【免费下载链接】telegrafAgent for collecting, processing, aggregating, and writing metrics, logs, and other arbitrary data.项目地址: https://gitcode.com/GitHub_Trending/te/telegraf创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考