实现了 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 中去
太麻烦了 我就不粘贴 代码了