Gin 的 /metrics 路由看不到内存/磁盘数据,因为 Gin 仅负责路由分发,不采集系统指标;promhttp.Handler() 仅暴露已注册到 Prometheus registry 的指标,而内存、磁盘等 OS 层指标需通过 gopsutil 手动采集并注册,或更规范地交由 node_exporter 专职采集。

直接暴露系统空闲内存和磁盘指标,不能靠 Gin 自身实现 —— 它不提供系统级指标采集能力,必须借助 prometheus/client_golang + 系统 Exporter(如 node_exporter)或 Go 原生库(如 gopsutil)手动拉取。
为什么 Gin 的 /metrics 路由里看不到内存/磁盘数据?
Gin 只负责 HTTP 路由分发,promhttp.Handler() 暴露的指标仅限已注册到 Prometheus registry 的内容。Gin 本身不采集系统指标,runtime.NumGoroutine() 这类运行时指标都得手动注册,更别说内存、磁盘这种 OS 层面数据。
- 常见错误:只在 Gin 中挂了
r.GET("/metrics", gin.WrapH(promhttp.Handler())),却没注册任何系统指标 →/metrics里只有默认的 Go runtime 指标(如go_goroutines),没有node_memory_MemFree_bytes或node_filesystem_free_bytes - 根本原因:Prometheus 的设计是「Pull 模型」,它期望你通过
node_exporter这类专用 Exporter 暴露系统指标,而不是让业务服务越权采集 - 例外场景:若你明确不想部署
node_exporter(比如单机轻量部署),才考虑用gopsutil在 Gin 服务内手动采集并注册
用 gopsutil 在 Gin 服务中手动采集空闲内存和磁盘
适合开发环境、单机部署或嵌入式场景。注意:gopsutil 是同步调用,采集耗时会影响请求处理,务必用 prometheus.NewGaugeVec + 后台 goroutine 定期更新,而非每次请求都采集。
- 安装依赖:
go get github.com/shirou/gopsutil/mem、go get github.com/shirou/gopsutil/disk - 定义指标变量(全局,启动时注册一次):
var ( memFree = prometheus.NewGaugeVec( prometheus.GaugeOpts{ Name: "system_memory_free_bytes", Help: "Free memory in bytes", }, []string{"device"}, ) diskFree = prometheus.NewGaugeVec( prometheus.GaugeOpts{ Name: "system_disk_free_bytes", Help: "Free disk space in bytes", }, []string{"device", "mountpoint"}, ) ) func init() { prometheus.MustRegister(memFree, diskFree) } - 启动后台采集(避免阻塞 HTTP handler):
go func() { ticker := time.NewTicker(10 * time.Second) defer ticker.Stop() for range ticker.C { // 内存 if v, err := mem.VirtualMemory(); err == nil { memFree.WithLabelValues("ram").Set(float64(v.Free)) } // 磁盘(例如根分区) if s, err := disk.Usage("/"); err == nil { diskFree.WithLabelValues("root", "/").Set(float64(s.Free)) } } }() - 别漏掉
prometheus.MustRegister():否则指标不会出现在/metrics输出中,且无报错提示
更推荐的方式:用 node_exporter + Prometheus server 主动拉取
生产环境强烈建议走标准路径 —— 让 node_exporter 负责采集,Gin 专注业务逻辑。这样既解耦,又避免 gopsutil 权限、性能和稳定性问题。
-
node_exporter默认监听:9100/metrics,暴露node_memory_MemFree_bytes、node_filesystem_free_bytes等标准指标 - Prometheus 配置 job 抓取:
scrape_configs: - job_name: 'node' static_configs: - targets: ['localhost:9100']
- Gin 服务只需暴露自己的业务指标(如
http_requests_total),与系统指标物理隔离 - 优势:无需在 Gin 进程里开 goroutine、不依赖 root 权限、指标命名规范、可复用 Grafana dashboard
真正容易被忽略的点是:系统指标和业务指标不该混在同一进程暴露。强行用 gopsutil 嵌入 Gin,看似省事,但会把监控责任耦合进业务代码,一旦采集卡顿或 panic,可能拖垮整个 HTTP 服务。node_exporter 的存在意义,就是划清这条边界。


















