You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Go SDK的OTEL实现中采集应用CPU信息?

获取OTEL runtime扩展的CPU使用率指标

你当前使用的OTEL runtime包仅聚焦Go运行时的内存、GC等专属指标,CPU使用率属于进程级系统指标,需要通过以下两种方式扩展采集:

方法一:引入Prometheus进程指标收集器(推荐)

Go OTEL生态中,进程级CPU指标可借助Prometheus官方的进程收集器实现,无需手动计算:

  1. 引入依赖
import (
    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/collectors"
    "go.opentelemetry.io/otel/sdk/metric"
    "go.opentelemetry.io/otel/sdk/resource"
    "go.opentelemetry.io/otel/semconv/v1.21.0"
)
  1. 整合到你的Meter Provider
    在初始化meterProvider时,将进程收集器注册到OTEL的Prometheus导出器中:
// 初始化Prometheus导出器
exporter, err := prometheus.New()
if err != nil {
    // 处理初始化错误
}

// 创建带进程指标的Meter Provider
meterProvider := metric.NewMeterProvider(
    metric.WithReader(exporter),
    metric.WithResource(resource.NewWithAttributes(
        semconv.SchemaURL,
        semconv.ServiceNameKey.String("your-service-name"),
    )),
)

// 注册进程收集器,自动采集CPU、内存等系统级指标
exporter.Register(collectors.NewProcessCollector(collectors.ProcessCollectorOpts{}))

// 启动原有的runtime指标采集
runtime.Start(runtime.WithMeterProvider(meterProvider), runtime.WithMinimumReadMemStatsInterval(time.Second))

完成后会自动生成process_cpu_seconds_total等CPU相关指标,通过监控系统计算该指标的增长率即可得到实时CPU使用率。

方法二:手动采集CPU时间(轻量方案)

如果不想引入额外依赖,可通过Go标准库手动计算CPU使用率:

  1. 定义OTEL仪表
import (
    "context"
    "go.opentelemetry.io/otel/metric"
    "runtime"
    "syscall"
    "time"
)

var cpuUsage metric.Float64Gauge

func initCPUMetric(meter metric.Meter) error {
    var err error
    cpuUsage, err = meter.Float64Gauge(
        "runtime.go.cpu.usage",
        metric.WithDescription("当前进程CPU使用率(0-1)"),
    )
    return err
}
  1. 定时采集并计算
func startCPUCollection(ctx context.Context) {
    var prevUser, prevSys uint64
    // 获取初始CPU时间
    user, sys, err := getProcessCPUTime()
    if err == nil {
        prevUser, prevSys = user, sys
    }

    ticker := time.NewTicker(time.Second)
    defer ticker.Stop()

    for {
        select {
        case <-ctx.Done():
            return
        case <-ticker.C:
            user, sys, err := getProcessCPUTime()
            if err != nil {
                continue
            }

            // 计算时间差并转换为秒
            userDiff := float64(user - prevUser) / 1e9
            sysDiff := float64(sys - prevSys) / 1e9
            totalDiff := userDiff + sysDiff

            // 结合CPU核心数计算使用率
            cpuCount := float64(runtime.NumCPU())
            usage := totalDiff / cpuCount

            cpuUsage.Record(ctx, usage)
            prevUser, prevSys = user, sys
        }
    }
}

// 获取进程用户态/内核态CPU时间(纳秒)
func getProcessCPUTime() (user, sys uint64, err error) {
    var rusage syscall.Rusage
    err = syscall.Getrusage(syscall.RUSAGE_SELF, &rusage)
    if err != nil {
        return 0, 0, err
    }
    user = uint64(rusage.Utime.Nano())
    sys = uint64(rusage.Stime.Nano())
    return
}
  1. 在应用初始化时启动采集
// 初始化MeterProvider后
meter := meterProvider.Meter("your-meter-name")
if err := initCPUMetric(meter); err == nil {
    go startCPUCollection(context.Background())
}
// 启动原runtime指标采集
runtime.Start(runtime.WithMeterProvider(meterProvider), runtime.WithMinimumReadMemStatsInterval(time.Second))

注意事项

  • 方法一的进程收集器会自动处理跨平台兼容、多核心计算等细节,稳定性更高,优先推荐。
  • 手动采集方案需注意跨平台适配(如Windows系统需替换syscall相关逻辑)。

内容的提问来源于stack exchange,提问作者Wiki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 13:32:40