请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

go使用opentelemetry来实现grpc链路追踪

实现了 opentelemetry 来进行链路追踪
但是
github 上
opentelemetry-python 和 opentelemetry-python-contrib 上的案例还是没看懂 希望讲解一下?

先上 Client段代码
和 他们的案例 相差甚远 不清楚 为什么用相同的库 代码居然不相同

package main

import (
	"PackageTest/20_jaeger_test/grpc_test_last/proto"
	"context"
	"fmt"
	"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/exporters/jaeger"
	"go.opentelemetry.io/otel/propagation"
	"go.opentelemetry.io/otel/sdk/resource"
	tracesdk "go.opentelemetry.io/otel/sdk/trace"
	semconv "go.opentelemetry.io/otel/semconv/v1.10.0"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"log"
	"time"
)

const (
	service = "mxshop"
)

// 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 string) (*tracesdk.TracerProvider, error) {
	// 创建 Jaeger 导出器
	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 a Resource.
		tracesdk.WithResource(resource.NewWithAttributes(
			semconv.SchemaURL,
			semconv.ServiceNameKey.String(service),
		)),
	)
	return tp, nil
}

func main() {
	// 用来创建 Jaeger 导出器
	tp, err := tracerProvider("http://192.168.16.196:14268/api/traces")
	if err != nil {
		log.Fatal(err)
	}

	// 注册我们的 TracerProvider 为全局的 所以任何导入
	// 将来的 instrumentation 将默认使用它
	otel.SetTracerProvider(tp)
	otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
	// 创建 子 context  用来传递给 子协程  用于 通信 底层实现的是 channel   cancel 用于关闭用
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// 当应用程序退出时,干净地关闭和刷新遥测
	defer func(ctx context.Context) {
		// 在关闭应用程序时,不要使其挂起
		ctx, cancel := context.WithTimeout(ctx, time.Second*5) // 从创建后 超过5秒后 关闭
		defer cancel()
		if err := tp.Shutdown(ctx); err != nil { // Shutdown按注册span处理器的顺序关闭它们
			log.Fatal(err)
		}
	}(ctx)

	//conn, err := grpc.Dial("127.0.0.1:8088", grpc.WithInsecure())
	conn, err := grpc.Dial("127.0.0.1:50051",
		grpc.WithTransportCredentials(insecure.NewCredentials()),
		grpc.WithUnaryInterceptor(otelgrpc.UnaryClientInterceptor()),   // 拦截普通的一次请求一次响应的rpc服务
		grpc.WithStreamInterceptor(otelgrpc.StreamClientInterceptor()), // 拦截流式的rpc服务
	)
	if err != nil {
		panic(err)
	}
	defer func(conn *grpc.ClientConn) {
		err := conn.Close()
		if err != nil {
			panic(err)
		}
	}(conn)

	c := proto.NewGreeterClient(conn)
	r, err := c.SayHello(context.Background(), &proto.HelloRequest{Name: "bobby"})
	if err != nil {
		panic(err)
	}
	fmt.Println(r.Message)
}

Server端 代码

package main

import (
	"PackageTest/6_grpc_test/proto"
	"context"
	"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/exporters/jaeger"
	"go.opentelemetry.io/otel/propagation"
	"go.opentelemetry.io/otel/sdk/resource"
	tracesdk "go.opentelemetry.io/otel/sdk/trace"
	semconv "go.opentelemetry.io/otel/semconv/v1.10.0"
	"google.golang.org/grpc"
	"log"
	"net"
	"time"
)

const (
	service = "mxshop-srv"
)

type Server struct {
	proto.UnimplementedGreeterServer // 这是 它内部实现的 的一个 结构体   我这边调用 以实现鸭子类型
}

func (s *Server) SayHello(ctx context.Context, request *proto.HelloRequest) (*proto.HelloReply, error) {
	return &proto.HelloReply{
		Message: "hello " + request.GetName(),
	}, nil
}

func tracerProvider(url string) (*tracesdk.TracerProvider, error) {
	// 创建 Jaeger 导出器
	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 a Resource.
		tracesdk.WithResource(resource.NewWithAttributes(
			semconv.SchemaURL,
			semconv.ServiceNameKey.String(service),
		)),
	)
	return tp, nil
}

func main() {
	// 用来创建 Jaeger 导出器
	tp, err := tracerProvider("http://192.168.16.196:14268/api/traces")
	if err != nil {
		log.Fatal(err)
	}

	// 注册我们的 TracerProvider 为全局的 所以任何导入
	// 将来的 instrumentation 将默认使用它
	otel.SetTracerProvider(tp)
	otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
	// 创建 子 context  用来传递给 子协程  用于 通信 底层实现的是 channel   cancel 用于关闭用
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// 当应用程序退出时,干净地关闭和刷新遥测
	defer func(ctx context.Context) {
		// 在关闭应用程序时,不要使其挂起
		ctx, cancel := context.WithTimeout(ctx, time.Second*5) // 从创建后 超过5秒后 关闭
		defer cancel()
		if err := tp.Shutdown(ctx); err != nil { // Shutdown按注册span处理器的顺序关闭它们
			log.Fatal(err)
		}
	}(ctx)

	// stream
	g := grpc.NewServer(grpc.UnaryInterceptor(otelgrpc.UnaryServerInterceptor()))
	proto.RegisterGreeterServer(g, &Server{})
	lis, err := net.Listen("tcp", "0.0.0.0:50051")
	if err != nil {
		panic("failed to listen" + err.Error())
	}
	err = g.Serve(lis)
	if err != nil {
		panic("failed to start grpc" + err.Error())
	}
}

效果图:
图片描述


后面 就是 集成到我们的 mxshop_srvs 和 mxshop-api 中去
太麻烦了 我就不粘贴 代码了

正在回答

1回答

  • 提问者 城中城 #1
    非常感谢!
    回复 有任何疑惑可以回复我~ 2022-08-02 16:54:57
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信