当前位置:首页 > 文章列表 > Golang > Go教程 > Go runtime/metrics 怎样读取运行时指标样本

Go runtime/metrics 怎样读取运行时指标样本

来源:17golang原创 2026-10-21 20:18:46 0浏览 收藏

读取 Go 运行时指标样本,要先用 metrics.All()取得描述符,再把需要的名称填入 []metrics.Sample,调用 metrics.Read,最后根据 Value.Kind()选择读取方法。不要把所有指标都当成 uint64,也不要把不支持的指标当成数值零。

设想一个报表服务准备升级工具链:原来只记录内存数字,现在还要观察调度等待分布。问题不只是加一个名称,而是采集器能否识别不同类型,以及下一次读取是否会覆盖前一次保留的直方图。下面只解决描述符、样本类型与读取,不扩展成监控平台部署教程。

官方文档:https://pkg.go.dev/runtime/metrics

升级工具链前先发现支持的指标

API 接口稳定不等于每个 Go 实现、每个版本都有完全相同的指标集合。迁移时先依据实际进程支持的描述符选择名称,而不是复制另一台机器的整份清单。

旧采集假设迁移后的处理
名字存在就有值先在 All 返回集合中匹配完整名称
数字都用 Uint64 读取按照 Value.Kind 分派
保存 Value 就保存了快照直方图数据需要独立复制

Description 包含 Name、Description、Kind 和 Cumulative。Name 的单位后缀属于标识的一部分,不能删掉后再匹配;Kind 指明表示类型,Cumulative 提醒你是否应把它视为累计量。图中的“指标目录”是 All 与 Description,“字段定义”是 Name、Kind、Cumulative;它们是目录和字段的组成关系。

指标目录和描述符字段的组成关系
图1:指标描述符结构说明图。分组区分目录与字段,连线表示包含关系,不是执行流程或采样结果。

把描述符转换为可读取的样本

以 goroutine 数量和调度延迟分布为例,下面程序先求所需名称与支持集合的交集,未找到的名称明确记录为不支持。保存为 main.go,使用包含 runtime/metrics 的 Go 工具链;程序不依赖第三方包。

package main

import (
    "fmt"
    "runtime"
    "runtime/metrics"
)

func main() {
    wanted := []string{
        "/sched/goroutines:goroutines",
        "/sched/latencies:seconds",
    }
    supported := make(map[string]metrics.Description)
    for _, d := range metrics.All() {
        supported[d.Name] = d // 完整名称包含单位后缀
    }

    samples := make([]metrics.Sample, 0, len(wanted))
    for _, name := range wanted {
        d, ok := supported[name]
        if !ok {
            fmt.Printf("不支持: %s\n", name)
            continue
        }
        fmt.Printf("指标=%s 类型=%v 累计=%t\n", name, d.Kind, d.Cumulative)
        samples = append(samples, metrics.Sample{Name: name})
    }
    fmt.Println("工具链:", runtime.Version())
    metrics.Read(samples) // 原地填充各样本的 Value

    for _, s := range samples {
        switch s.Value.Kind() {
        case metrics.KindUint64:
            fmt.Printf("%s 数值=%d\n", s.Name, s.Value.Uint64())
        case metrics.KindFloat64:
            fmt.Printf("%s 数值=%g\n", s.Name, s.Value.Float64())
        case metrics.KindFloat64Histogram:
            h := s.Value.Float64Histogram()
            fmt.Printf("%s 桶数=%d 边界数=%d\n", s.Name, len(h.Counts), len(h.Buckets))
        case metrics.KindBad:
            fmt.Printf("%s 不可用\n", s.Name) // 不能记作零值
        default:
            fmt.Printf("%s 未处理类型=%v\n", s.Name, s.Value.Kind())
        }
    }
}

代码展示的是读取方式,不给出伪造的运行数字。读者执行后应看到受支持名称的类型说明和各自对应的数据形式;实际数量、桶数和样本值取决于运行环境。采样一次并不能推出服务是否异常。

读取结果必须按 Kind 分派

Uint64、Float64 和 Float64Histogram 不是任意可互换的转换函数,调用与类型不符的访问器会 panic。即使当前选择的两个指标类型已知,保留 switch 仍能把采集器对类型的假设写清楚。

直方图包含 Counts 与 Buckets:第 i 个计数对应区间 [Buckets[i], Buckets[i+1]),边界数比桶数多一。它不是“边界值对应的精确样本列表”,不能直接把某个边界打印成真实 P99。本文仅读取结构,不实现分位数估算。

Sample 包含 Name 与 Value,Value 的 Kind 决定读取类型;对于直方图,Value 关联 Float64Histogram,后者包含 Counts、Buckets。图中的“样本容器”“类型数据”按这六个实体分组说明。

样本值与直方图计数边界的静态关系
图2:指标值结构说明图。Counts 和 Buckets 是直方图组成,不是两个独立指标;连线不暗示读取先后或运行结果。

复用样本时怎样保留独立快照

重复使用同一 samples 切片可减少重复准备,但 Read 正在写入时,其他 goroutine 不应读取或修改关联值。直方图底层存储还可能被后续 Read 复用;只复制 Sample 或保存直方图指针并不能保证独立。

下面是独立复制函数,放在导入 runtime/metrics 的文件中。应在没有并发 Read 的受控位置调用,再把副本交给消费者;复制过程本身不是同步手段。

// 在采样器独占样本时调用,复制两组底层数据
func copyHistogram(h *metrics.Float64Histogram) *metrics.Float64Histogram {
    if h == nil {
        return nil
    }
    return &metrics.Float64Histogram{
        Counts: append([]uint64(nil), h.Counts...),
        Buckets: append([]float64(nil), h.Buckets...),
    }
}

一种简单所有权安排是由单个采样 goroutine 管理 samples,在两次 Read 之间提取标量、深拷贝直方图,再通过通道传递自有记录。不要把原始 Value 指针交出去后立刻复用切片,也不要为了避开复制而让消费者无锁读取正在更新的桶计数。

升级前后需要对比什么

迁移清单包括:实际工具链版本、完整指标名称、描述文字、Kind、Cumulative,以及你自己的缺失指标策略。可选指标缺失可以跳过并报告;核心指标缺失是否阻止服务启动由业务明确决定,不能静默填零。

比较累计量时还需注意进程是否重启。累计值是总量,不是当前速率;不同进程直接相减没有意义。直方图差分还需确认两份边界一致,不能仅按相同下标把不同版本的桶相减。采集开销应在真实采样频率下测量,不承诺所有读取都零分配或没有影响。

Read 有错误返回值吗?

没有。单个值的不可用状态通过 KindBad 表达,因此不能靠 err 判断这次选择的所有名称都有效。

能用它查看另一进程吗?

它读取当前 Go 进程的运行时指标,不是操作系统的远程进程查询接口。若需外部访问,要另行设计导出机制和访问边界。

一次 Read 能当作整个系统的严格同时刻快照吗?

不要作这种假设。它用于批量采集所选指标,不应据此宣称所有互不相关指标都形成全局事务快照。

最终应交付一份能发现、分派和保留样本的采集器,而不是固定写死数值类型的指标名称列表。参考:runtime/metrics 文档、Go 官方采样接口源码。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Go database/sql.Rows.NextResultSet 怎样读取多结果集Go database/sql.Rows.NextResultSet 怎样读取多结果集
上一篇
Go database/sql.Rows.NextResultSet 怎样读取多结果集
琥珀折光手机壁纸怎样形成细长纵向构图
下一篇
琥珀折光手机壁纸怎样形成细长纵向构图
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    582次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    620次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    651次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    616次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    432次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码