docker-ce 中的 Prometheus client_golang 剖析:从埋点库原理到 dockerd /metrics 的落地实现 容器运行时云原生【免费下载链接】docker-ce:warning: This repository is deprecated and will be archived (Docker CE itself is NOT deprecated) see the https://github.com/docker/docker-ce/blob/master/README.md :warning:项目地址https://gitcode.com/gh_mirrors/do/docker-ce点击查看免费下载docker-ce 仓库在 CLI 与 Engine 两个组件中都以 vendored源码内嵌方式内置了 Prometheus 官方 Go 客户端库github.com/prometheus/client_golang锁定版本 v1.6.0。本文以 client_golang 的 README 为骨架完整梳理该库的定位与组成部分、埋点instrumentation核心用法与自定义 Collector 原理、promhttp 子包的 HTTP 暴露机制与可调参数并结合 docker-ce 源码dockerd --metrics-addr、/metrics端点、stateCounter自定义采集器说明这套库在 Docker 守护进程中的真实调用链帮助读者既能读懂这份第三方 README也能掌握在自己的 Go 服务中接入 Prometheus 埋点的完整方案。一、这份 README 在 docker-ce 仓库中的位置client_golang是 Prometheus 的官方 Go 客户端库。docker-ce 通过 vendor 机制将其完整源码复制进仓库保证构建时不依赖外部网络拉取。两个组件的依赖清单都将其锁定在同一提交components/cli/vendor.conf 第 58 行与 components/engine/vendor.conf 第 159 行github.com/prometheus/client_golang 6edbbd9e560190e318cdc5b4d3e630b442858380 # v1.6.0README 同时声明了运行前提要求 Go 1.9 或更高版本旧版本 Go 的最低补丁号为 Go 1.9.7 与 Go 1.10.3而 vendor 目录内的 go.mod 显示该版本实际编译要求go 1.11依赖prometheus/common v0.9.1、prometheus/client_model v0.2.0、prometheus/procfs v0.0.11等。从 vendored 目录结构看README 描述的完整库api/、examples/、push/等在 docker-ce 中只内嵌了埋点部分即prometheus/包及其promhttp子包、internal/metric.go没有 HTTP API 客户端与示例目录——这正与 dockerd 的实际用途吻合它只需要暴露指标不需要查询 Prometheus。1.1 库的两大部分与稳定性边界README 将该库划分为两个独立部分应用埋点库prometheus目录用于给 Go 应用代码打点是稳定部分Prometheus HTTP API 客户端api/prometheus目录用于编写向 Prometheus 服务器查询时序数据的 Go 程序README 明确标注其仍处于 alpha 阶段。关于版本策略README 给出了一条对使用者很重要的规则仓库总体遵循 Semantic Versioning但api/…下的 API 客户端以及 CHANGELOG 中标记为EXPERIMENTAL的特性发生破坏性变更时不会触发新的 major 版本需要破坏性变更的稳定特性被归入 v2 里程碑v2 在独立分支上开发发布后 v1 与 v2 会有一段共存期以便平滑迁移。因此升级该库时埋点代码可以按 SemVer 预期管理而一旦用到api/prometheus客户端就应当预期其接口可能跨小版本变化。1.2model、extraction、text去了哪里README 专门解释了三个失踪的包这是理解 Prometheus 生态代码分布的关键原包现位置作用modelprometheus/common/model时间序列模型等公共类型extraction/textprometheus/common/expfmt指标的抽取与文本格式编解码在 docker-ce 的 vendored 代码中可以直接印证promhttp/http.go 导入的正是github.com/prometheus/common/expfmt用它来做 Content-Type 协商与编码expfmt.Negotiate、expfmt.NewEncoder。二、埋点库prometheus 包的核心用法vendored 的 doc.go 是该包的完整使用说明README 指引读者阅读它。下面按最小可用示例 → 数据类型 → 自定义 Collector → 注册表的顺序展开。2.1 最小完整示例一个暴露两个指标的 HTTP 服务doc.go 中给出的基础示例是一个可独立运行的完整程序导出一个无标签的 GaugeCPU 温度和一个带标签的 CounterVec硬盘错误数并通过promhttp.Handler()在/metrics端点暴露package main import ( log net/http github.com/prometheus/client_golang/prometheus github.com/prometheus/client_golang/prometheus/promhttp ) var ( cpuTemp prometheus.NewGauge(prometheus.GaugeOpts{ Name: cpu_temperature_celsius, Help: Current temperature of the CPU., }) hdFailures prometheus.NewCounterVec( prometheus.CounterOpts{ Name: hd_errors_total, Help: Number of hard-disk errors., }, []string{device}, ) ) func init() { // Metrics have to be registered to be exposed: prometheus.MustRegister(cpuTemp) prometheus.MustRegister(hdFailures) } func main() { cpuTemp.Set(65.3) hdFailures.With(prometheus.Labels{device: /dev/sda}).Inc() // The Handler function provides a default handler to expose metrics // via an HTTP server. /metrics is the usual endpoint for that. http.Handle(/metrics, promhttp.Handler()) log.Fatal(http.ListenAndServe(:8080, nil)) }从该示例可以直接归纳出埋点三要素构造指标用NewGauge/NewCounterVec等构造函数参数是…Opts结构体GaugeOpts、CounterOpts、SummaryOpts、HistogramOptsName与Help是必填信息CounterVec 的额外参数[]string{device}声明了标签维度注册prometheus.MustRegister(...)将 Collector 注册进默认注册表全局DefaultRegisterer不注册的指标不会被暴露暴露promhttp.Handler()挂在 HTTP mux 的/metrics路径上供 Prometheus 抓取。2.2 四种基础指标类型与向量Vec形态doc.go 指出基础用法只需理解四种指标类型及其向量版本类型向量版本语义GaugeGaugeVec可增可减的瞬时值CounterCounterVec只增计数器通常命名以_total结尾SummarySummaryVec客户端侧分位数统计HistogramHistogramVec服务端分桶统计支持 PromQL 计算分位数Prometheus 数据模型的另一半是按标签维度切分样本这正是 Vec 系类的存在意义一个CounterVec实际上是同名同标签集、不同标签值的一组 Metric。类型上有两个易混淆点doc.go 明确说明只有基础类型Gauge/Counter/Summary/Histogram实现了Metric接口指标与其向量版本都实现了Collector接口Gauge等基础类型本身是接口而GaugeVec等向量版本是具体类型而非接口。2.3 自定义 CollectorDescribe / Collect 契约collector.go 定义了Collector接口它有两个方法构成自描述 按需采集的契约Describe(chan- *Desc)向通道发送该 Collector 可能产生的所有指标的超集描述符Desc。发送空描述即把 Collector 标记为unchecked——注册时不做一致性检查一致性责任由实现方承担不一致会在抓取时才暴露为错误Collect(chan- Metric)抓取时被注册表调用把每个采集到的 Metric 通过通道发出。两个方法都要求并发安全。doc.go 给出了两类典型场景一是把已有指标镜像进 Prometheus库内processCollector、goCollector、expvarCollector就是实例二是只需要在采集时调用一个函数取 float 值时用GaugeFunc、CounterFunc、UntypedFunc这类快捷方式。对于采集期凭空创建常量指标则用NewConstMetric/NewConstHistogram/NewConstSummary及各自的Must…变体不确定镜像指标是 Counter 还是 Gauge 时用Untyped类型。docker-ce 中的真实用例Engine 的 daemon/metrics.go 定义了一个stateCounter结构体恰好完整实现了这套契约——它持有一张容器 ID → 状态标签的 mapDescribe直接转发预建的*prometheus.DescCollect时统计 running/paused/stopped 三个数量并调用prometheus.MustNewConstMetric(ctr.desc, prometheus.GaugeValue, ...)现场构造三个常量 Gauge 指标func (ctr *stateCounter) Describe(ch chan- *prometheus.Desc) { ch - ctr.desc } func (ctr *stateCounter) Collect(ch chan- prometheus.Metric) { running, paused, stopped : ctr.get() ch - prometheus.MustNewConstMetric(ctr.desc, prometheus.GaugeValue, float64(running), running) ch - prometheus.MustNewConstMetric(ctr.desc, prometheus.GaugeValue, float64(paused), paused) ch - prometheus.MustNewConstMetric(ctr.desc, prometheus.GaugeValue, float64(stopped), stopped) }这与 README 所指custom Collector 用于把外部已有的数字镜像成 Prometheus 指标的说明完全对应容器状态并不天然属于 Prometheus 数据模型dockerd 通过自定义 Collector 在每次抓取时镜像进来。2.4 注册表默认注册表与自定义注册表doc.go 对 Registry 的说明可以概括为MustRegister出错即 panicRegister返回 error 便于处理。注册期就检查 Collector 与已注册指标的一致性目的是在启动时而非抓取时发现不一致全局DefaultRegisterer即默认注册表NewRegistry可创建自定义注册表还可自实现Registerer/Gatherer接口。自定义注册表的用途包括避免全局状态、同时暴露多套指标、隔离测试环境默认注册表出厂自带两个 CollectorGo 运行时指标NewGoCollector与进程指标NewProcessCollector。这一点在 registry.go 的源码注释中可以直接确认a process collector (currently on Linux only)——即 dockerd 的/metrics端点里出现的go_*、process_*系列指标都是默认注册表免费提供的。三、promhttp把指标经 HTTP 暴露出去的子包README 的HTTP Exposition部分指向promhttp子包。vendored 的 promhttp/http.go 提供了三层能力。3.1Handler()与HandlerFor()Handler()作用于DefaultGatherer、使用默认HandlerOpts的一键式 handler。其默认行为是首个错误即返回 HTTP 错误、无错误日志、客户端请求压缩时启用 gzip。源码显示http.go#L74-L78它内部等价于对HandlerFor的结果再套一层InstrumentMetricHandlerHandlerFor(reg, opts)为任意Gatherer创建未自埋点的 handler行为完全由HandlerOpts决定。HandlerOptshttp.go#L305-L353各字段及默认行为字段类型作用与默认值ErrorLogLogger只需Println收集/发送错误时的日志输出nil 则不记录ErrorHandlingHandlerErrorHandling三种策略见下默认HTTPErrorOnErrorRegistryRegisterer非 nil 时额外注册错误计数器promhttp_metric_handler_errors_total按cause分gathering/encoding两个标签值注册失败会 panicDisableCompressionbooltrue 时永不压缩即使客户端 Accept-Encoding 含 gzipMaxRequestsInFlightint并发抓取上限超出返回 503。0 或负数表示不限制Timeouttime.Duration处理超时超时以 503 应答。0 或负数无超时。源码注释提醒超时只是提前结束 HTTP 请求后台的指标采集仍会继续跑完因此慢 Collector 建议自己实现内部超时EnableOpenMetricsbooltrue 时把实验性的 OpenMetrics 编解码加入内容协商expfmt.NegotiateIncludingOpenMetrics这是传输 exemplar 的唯一途径注意quantile/le标签为整数值时会带.0后缀从而改变 series 身份ErrorHandling的三个常量http.go#L273-L294HTTPErrorOnError默认首个错误即返回 500 并写入错误信息注意一旦 payload 开始流出就无法再发 HTTP 错误因此编码阶段出错只会中止发送ContinueOnError尽力而为能发多少发多少仅在一条指标都发不出时才返回 500。文档建议搭配ErrorLog与Registry使用以便通过日志与错误计数器发现异常PanicOnError首个错误即 panic适合crash-only应用。抓取请求的处理流程对应HandlerFor内的 handler 主体先按MaxRequestsInFlight的并发信号量限流再reg.Gather()收集全部 MetricFamily按请求头协商输出格式默认 Prometheus 文本格式开启后可能协商为 OpenMetrics若客户端接受 gzip 则从包级sync.Pool复用的gzip.Writer压缩输出最后逐 family 编码发送。3.2 自埋点InstrumentMetricHandlerHandler()返回的 handler 自带两个关于抓取本身的指标http.go#L232-L265promhttp_metric_handler_requests_totalCounterVec按 HTTP 状态码预置 200/500/503 标签值累计抓取次数promhttp_metric_handler_requests_in_flightGauge当前正在并发处理的抓取数。函数是幂等注册重复调用会捕获AlreadyRegisteredError并复用已存在的 Collector。文档还提示in-flight Gauge 会包含正在进行中的这次抓取自身而 requests 计数器要等抓取完成、状态码已知后才自增若要统计抓取耗时应使用 Prometheus 服务端侧的scrape_duration_seconds。3.3 中间件给任意 http.Handler / RoundTripper 打点http.go 的包注释说明promhttp还提供两类中间件包装器InstrumentHandlerX系列包装http.Handler如InstrumentHandlerCounter、InstrumentHandlerInFlight、InstrumentHandlerDuration、InstrumentHandlerRequestSize、InstrumentHandlerResponseSizeInstrumentRoundTripperX系列包装http.RoundTripper用于给出站 HTTP 客户端打点。docker-ce 的直接证据Engine 侧的docker/go-metrics封装层 handler.go 的InstrumentHandlerFunc正是逐一调用上述五个promhttp.InstrumentHandler*函数按配置HTTPHandlerOpts中DurationBuckets默认[.005, .01, .025, ..., 60]RequestSizeBuckets/ResponseSizeBuckets默认prometheus.ExponentialBuckets(1024, 2, 22)即 1KiB 到 4GiB为 dockerd 的 API 请求加上耗时、请求/响应大小与计数埋点。四、docker-ce 中的落地调用链--metrics-addr到/metrics把 README 描述的库能力放回 docker-ce 仓库可以得到一条完整的实现链命令行开关cmd/dockerd/config.go 定义了--metrics-addr标志Set default address and port to serve the metrics api on启动服务cmd/dockerd/daemon.go 在启动流程中调用startMetricsServer(cli.Config.MetricsAddress)挂载端点cmd/dockerd/metrics.go 中startMetricsServer若收到非空地址则在独立 TCP 端口上起一个http.ServeMux把metrics.Handler()来自docker/go-metrics挂到/metrics路径日志打印 metrics API listening on %s桥接到 client_golanggo-metrics的Handler()直接return promhttp.Handler()go-metrics/handler.go#L38-L40——即 README 所指引的默认注册表 默认 HandlerOpts 路径业务指标注册daemon/metrics.go 的init()用docker/go-metrics的命名空间 API 声明了container_actions按 start/changes/commit/create/delete 分标签的 Timer、network_actions、engine含 version/commit/architecture 等 9 个标签的 Info Gauge、engine_cpus、engine_memory、health_checks等指标外加第二节介绍的stateCounter自定义 Collector统一经metrics.Register(ns)进入全局注册表插件扩展daemon/metrics.go还定义了MetricsCollector类型的插件协议StartMetrics/StopMetricsRPC允许外部插件进程把自定义指标汇入同一套采集体系。也就是说dockerd 对外提供的每一个指标样本最终都经过 README 所指认的prometheus包完成采集、经promhttp子包完成编码与压缩后从--metrics-addr指定的端点流出。五、使用与升级注意事项结合 README 原文与 vendored 源码给维护者与使用者几条可操作的边界条件版本锁定docker-ce 两处 vendor.conf 都锁定 v1.6.0按 README 的 SemVer 承诺prometheus埋点包属于稳定 API但api/prometheus客户端不承诺稳定Go 版本门槛库声明要求 Go ≥ 1.9旧版本最低补丁 Go 1.9.7 / Go 1.10.3vendored go.mod 的编译指令为 go 1.11依赖拆分不要在本库中找model、extraction、text——它们已迁移到prometheus/commonmodel与expfmt两个包本仓库 vendored 的expfmt即其消费方默认注册表已含运行时/进程指标使用默认注册表时go_*、process_*指标自动存在NewProcessCollector当前仅 Linux 生效自定义注册表则可完全自主控制端点暴露的并发与超时生产暴露/metrics时优先考虑HandlerOpts的MaxRequestsInFlight与Timeout并为慢速 Collector 配置独立超时README 所指实现现状是超时后采集仍在后台完成其结果被丢弃。综上这份 vendored README 是理解 docker-ce 监控体系入口的钥匙它界定了client_golang的两部分职责与稳定性边界而prometheus/promhttp的源码与 dockerd 的--metrics-addr实现链则展示了这套库在 Docker 工程中的标准落地方式——声明式构造指标、注册表统一采集、promhttp一键暴露、自定义 Collector 镜像外部状态。赞分享容器运行时云原生【免费下载链接】docker-ce:warning: This repository is deprecated and will be archived (Docker CE itself is NOT deprecated) see the https://github.com/docker/docker-ce/blob/master/README.md :warning:项目地址https://gitcode.com/gh_mirrors/do/docker-ce点击查看免费下载相关推荐CubeFS 依赖解析armon/go-metrics 指标埋点库原理与实战指南CubeFS 依赖解析armon/go metrics 指标埋点库原理与实战指南 本文以 CubeFS 仓库内 vendored 的 go metrics 官存储分布式文件系统对象存储云原生终极指南Reqwest响应时间监控从Metrics到Prometheus落地终极指南Reqwest响应时间监控从Metrics到Prometheus落地 Reqwest是一个简单而强大的Rust HTTP客户端它提供了异步和阻塞两种后端开发工具GEM-X安全与伦理考量隐私保护与负责任AI的最佳实践指南GEM X安全与伦理考量隐私保护与负责任AI的最佳实践指南 GEM X通用人体运动模型是NVIDIA开发的革命性单目视频3D人体姿态估计模型能够从动态摄上一篇如何安全导出浏览器CookieGet cookies.txt LOCALLY终极指南下一篇4步完整教程用OpenCore Legacy Patcher让老旧Mac完美升级最新系统创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考