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

如何使用Go SDK向OpenTelemetry推送指标?新手技术求助

问题解答

核心概念梳理

  • MeterProvider:指标体系的核心入口,负责生成Meter实例、管理指标生命周期,同时通过绑定Reader来配置指标的导出规则。所有指标(如Counter、Gauge)的创建都必须通过它提供的Meter来完成。
  • Reader:MeterProvider与Exporter之间的中转层,负责从MeterProvider拉取指标数据,再交付给Exporter发送到目标系统(比如OTel Collector、Prometheus)。不同Reader对应不同导出策略:PeriodicReader是定期主动推送,Prometheus的Reader则是暴露HTTP端点让Prometheus主动拉取。

代码问题修正

你的代码存在两个关键问题:

  1. OTLP的Reader创建后未绑定到MeterProvider,导致OTLP导出逻辑完全失效;
  2. 程序执行完指标添加后直接退出,Reader没有足够时间完成指标的收集与推送。

修正后的完整代码:

package main

import (
	"context"
	"net/http"
	"time"

	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/exporters/prometheus"
	"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc"
	"go.opentelemetry.io/otel/metric"
	"go.opentelemetry.io/otel/metric/instrument"
	"go.opentelemetry.io/otel/sdk/metric"
	"go.opentelemetry.io/otel/sdk/resource"
	semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
)

func main() {
	ctx := context.Background()

	// 创建服务标识资源,用于在监控系统中区分不同服务
	res, err := resource.New(ctx,
		resource.WithAttributes(
			semconv.ServiceName("my-service"),
			attribute.String("env", "dev"),
		),
	)
	if err != nil {
		panic(err)
	}

	// 建立与OTel Collector的GRPC连接
	ctx, cancel := context.WithTimeout(ctx, time.Second)
	defer cancel()
	conn, err := grpc.DialContext(ctx, "localhost:4317",
		grpc.WithTransportCredentials(insecure.NewCredentials()),
		grpc.WithBlock(),
	)
	if err != nil {
		panic(err)
	}
	defer conn.Close()

	// 初始化OTLP指标导出器
	otlpExporter, err := otlpmetricgrpc.New(ctx, otlpmetricgrpc.WithGRPCConn(conn))
	if err != nil {
		panic(err)
	}

	// 初始化Prometheus导出器
	promExporter, err := prometheus.New()
	if err != nil {
		panic(err)
	}
	// 启动Prometheus指标暴露的HTTP服务,默认端口9090
	go func() {
		http.Handle("/metrics", promExporter)
		if err := http.ListenAndServe(":9090", nil); err != nil {
			panic(err)
		}
	}()

	// 创建两个Reader,分别对应OTLP定期推送和Prometheus拉取
	otlpReader := metric.NewPeriodicReader(otlpExporter, metric.WithInterval(1*time.Second))
	promReader := promExporter.Reader()

	// 初始化MeterProvider,同时绑定两个Reader,实现指标多端导出
	meterProvider := metric.NewMeterProvider(
		metric.WithResource(res),
		metric.WithReader(otlpReader),
		metric.WithReader(promReader),
	)
	// 设置全局MeterProvider,方便后续代码在任意位置获取Meter
	otel.SetMeterProvider(meterProvider)
	// 程序退出前确保所有指标导出完成
	defer func() {
		if err := meterProvider.Shutdown(ctx); err != nil {
			panic(err)
		}
	}()

	// 获取业务专属的Meter实例
	meter := meterProvider.Meter("github.com/your-org/your-service")

	// 创建Counter类型指标
	counter, err := meter.Float64Counter("foo", instrument.WithDescription("a simple counter"))
	if err != nil {
		panic(err)
	}
	// 给指标添加数值,可附带自定义属性丰富维度
	counter.Add(ctx, 5, instrument.WithAttributes(attribute.String("key", "value")))

	// 阻塞程序运行,避免指标未推送就退出
	select {}
}

后续验证与扩展步骤

  1. 启动OTel Collector:确保本地OTel Collector已运行,配置好OTLP指标接收端点(默认4317),并设置好目标导出后端(如Prometheus、Grafana);
  2. 验证Prometheus指标:访问http://localhost:9090/metrics,能看到名为foo的指标;
  3. 验证OTLP推送:查看OTel Collector日志,或在Grafana等后端查看是否收到my-service的foo指标;
  4. 扩展指标类型:尝试创建Gauge、Histogram等其他指标类型,添加更多属性来丰富监控维度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 19:23:28