golang链路追踪

136 阅读1分钟

golang的链路追踪一般都是用的jeager,今天去官方仓库看,发现,jaeger的client已经停止维护了,一头雾水,后面研究了一番,发现有一个叫做OpenTelemetry的东西,规范了trace,metric的接口,希望大家都按照统一的标准去做。

仓库地址:github.com/open-teleme…

关于OpenTelemetry使用的一些文章: www.cnblogs.com/charlieroro… my.oschina.net/yunduansing…

jaeger实现的代码,拷贝了一份过来

引入

go get go.opentelemetry.io/otel/sdk
go get go.opentelemetry.io/otel/exporters/stdout/stdouttrace

简单封装 jaeger.go

package jaeger

import (
	"context"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/exporters/jaeger"
	"go.opentelemetry.io/otel/sdk/resource"
	tracesdk "go.opentelemetry.io/otel/sdk/trace"
	semconv "go.opentelemetry.io/otel/semconv/v1.7.0"
	"go.opentelemetry.io/otel/trace"
	"os"
)

// tracerProvider returns an OpenTelemetry TracerProvider configured to use
// the Jaeger exporter that will send spans to the provided url. The returned
// TracerProvider will also use a Resource configured with all the information
// about the application.
func tracerProvider(url, serviceName, environment, id string) (*tracesdk.TracerProvider, error) {
	// Create the Jaeger exporter
	exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(url)))
	if err != nil {
		return nil, err
	}
	tp := tracesdk.NewTracerProvider(
		// Always be sure to batch in production.
		tracesdk.WithBatcher(exp),
		// Record information about this application in an Resource.
		tracesdk.WithResource(resource.NewWithAttributes(
			semconv.SchemaURL,
			semconv.ServiceNameKey.String(serviceName),
			attribute.String("environment", environment),
			attribute.String("ID", id),
		)),
	)
	return tp, nil
}

func NewJaeger(ctx context.Context, url, serviceName, environment, id string) {
	tp, err := tracerProvider(url, serviceName, environment, id)
	if err != nil {
		return
	}

	// Register our TracerProvider as the global so any imported
	// instrumentation in the future will default to using it.
	otel.SetTracerProvider(tp)
	ctx, cancel := context.WithCancel(ctx)
	sig := make(chan os.Signal, 1)
	select {
	case <-ctx.Done():
	case <-sig:

	}
	if err := tp.Shutdown(ctx); err != nil {
		log.Fatal(err)
	}
	cancel()
}

func StartFromContext(ctx context.Context, tracer, spanName string) (context.Context, trace.Span) {
	tp := otel.GetTracerProvider()
	t := tp.Tracer(tracer)
	return t.Start(ctx, spanName)
}

使用

go jaeger.NewJaeger(ctx, url, serviceName, environment, id)
其中 ctx 表示 go 的 context.Context,url 是 Jaeger ui 地址,serviceName 指的是微服务名,environment 指的是运行环境如 dev,id 随便传

然后就可以在 service 里面直接使用:
_, span := jaeger.StartFromContext(ctx, "trancer", "spanname")
defer span.End()
span.SetAttributes(attribute.String("data from", "redis cache"))
最后再去 jaeger ui 就能看到开头的效果。