gRPC – GoLang – Stackdriver 追踪器

huangapple go评论91阅读模式
英文:

gRPC - GoLang - Stackdriver tracer

问题

我正在尝试让stackdrivergRPC一起工作,我需要一些帮助。我已经查看了以下两个链接作为参考,但仍然无法使其工作:

为了简单起见,我只是使用了gRPC的Hello World示例。这是我的客户端代码:

func main() {

	// Set up a connection to the server.
	conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure(), grpc.WithUnaryInterceptor(grpc.UnaryClientInterceptor(clientInterceptor)))
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	defer conn.Close()
	c := pb.NewGreeterClient(conn)

	ctx := context.Background()

	tc, err := trace.NewClient(ctx, "{PROJECT-ID}")
	if err != nil {
		log.Fatal(err)
	}

	span := tc.NewSpan("/greeter/SayHello")
	defer span.Finish()

	ctx = trace.NewContext(ctx, span)

	r, err := c.SayHello(ctx, &pb.HelloRequest{Name: "world"})
	if err != nil {
		log.Fatalf("could not greet: %v", err)
	}

	println("Response:", r.Message)
}

func clientInterceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
	// trace current request w/ child span
	span := trace.FromContext(ctx).NewChild(method)
	defer span.Finish()

	// new metadata, or copy of existing
	md, ok := metadata.FromContext(ctx)
	if !ok {
		md = metadata.New(nil)
	} else {
		md = md.Copy()
	}

	// append trace header to context metadata
	// header specification: https://cloud.google.com/trace/docs/faq
	md["X-Cloud-Trace-Context"] = append(
		md["X-Cloud-Trace-Context"], fmt.Sprintf("%s/%d;o=1", span.TraceID(), 0),
	)
	ctx = metadata.NewContext(ctx, md)

	return invoker(ctx, method, req, reply, cc, opts...)
}

这是我的gRPC服务器代码:

// server is used to implement helloworld.GreeterServer.
type server struct{}

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
	println("HERE")
	return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}

func main() {
	lis, err := net.Listen("tcp", ":50051")
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}

	ctx := context.Background()
	tc, err := trace.NewClient(ctx, "{PROJECT-ID}")
	if err != nil {
		log.Fatal(err)
	}

	s := grpc.NewServer(EnableGRPCTracingServerOption(tc))
	pb.RegisterGreeterServer(s, &server{})

	println("listening on :50051")
	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}

// EnableGRPCTracingServerOption enables parsing google trace header from metadata
// and adds a new child span to the incoming request context.
func EnableGRPCTracingServerOption(traceClient *trace.Client) grpc.ServerOption {
	return grpc.UnaryInterceptor(serverInterceptor(traceClient))
}

func serverInterceptor(traceClient *trace.Client) grpc.UnaryServerInterceptor {
	return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
		// fetch metadata from request context
		md, ok := metadata.FromContext(ctx)
		if !ok {
			md = metadata.New(nil)
		}
		header := strings.Join(md["X-Cloud-Trace-Context"], "")

		// create new child span from google trace header, add to
		// current request context
		span := traceClient.SpanFromHeader(info.FullMethod, header)
		defer span.Finish()
		ctx = trace.NewContext(ctx, span)

		return handler(ctx, req)
	}
}

当我运行客户端以启动跟踪时,我收到以下错误:

rpc error: code = 13 desc = stream terminated by RST_STREAM with error code: 1

我感到困惑,因为我没有看到任何关于身份验证的其他信息;只提供项目ID可能不足以启动特定项目的跟踪。我漏掉了什么?

英文:

I am trying to get the stackdriver tracer to work with gRPC and I need some help. I have been looking at these two links for reference and I still can't get it to work:

For simplicity, I am just working with the hello world gRPC example. Here's my client:

func main() {
// Set up a connection to the server.
conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure(), grpc.WithUnaryInterceptor(grpc.UnaryClientInterceptor(clientInterceptor)))
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewGreeterClient(conn)
ctx := context.Background()
tc, err := trace.NewClient(ctx, "{PROJECT-ID}")
if err != nil {
log.Fatal(err)
}
span := tc.NewSpan("/greeter/SayHello")
defer span.Finish()
ctx = trace.NewContext(ctx, span)
r, err := c.SayHello(ctx, &pb.HelloRequest{Name: "world"})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
println("Response:", r.Message)
}
func clientInterceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
// trace current request w/ child span
span := trace.FromContext(ctx).NewChild(method)
defer span.Finish()
// new metadata, or copy of existing
md, ok := metadata.FromContext(ctx)
if !ok {
md = metadata.New(nil)
} else {
md = md.Copy()
}
// append trace header to context metadata
// header specification: https://cloud.google.com/trace/docs/faq
md["X-Cloud-Trace-Context"] = append(
md["X-Cloud-Trace-Context"], fmt.Sprintf("%s/%d;o=1", span.TraceID(), 0),
)
ctx = metadata.NewContext(ctx, md)
return invoker(ctx, method, req, reply, cc, opts...)
}

.. and my gRPC server:

// server is used to implement helloworld.GreeterServer.
type server struct{}
// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
println("HERE")
return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}
func main() {
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
ctx := context.Background()
tc, err := trace.NewClient(ctx, "{PROJECT-ID}")
if err != nil {
log.Fatal(err)
}
s := grpc.NewServer(EnableGRPCTracingServerOption(tc))
pb.RegisterGreeterServer(s, &server{})
println("listening on :50051")
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
// EnableGRPCTracingServerOption enables parsing google trace header from metadata
// and adds a new child span to the incoming request context.
func EnableGRPCTracingServerOption(traceClient *trace.Client) grpc.ServerOption {
return grpc.UnaryInterceptor(serverInterceptor(traceClient))
}
func serverInterceptor(traceClient *trace.Client) grpc.UnaryServerInterceptor {
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
// fetch metadata from request context
md, ok := metadata.FromContext(ctx)
if !ok {
md = metadata.New(nil)
}
header := strings.Join(md["X-Cloud-Trace-Context"], "")
// create new child span from google trace header, add to
// current request context
span := traceClient.SpanFromHeader(info.FullMethod, header)
defer span.Finish()
ctx = trace.NewContext(ctx, span)
return handler(ctx, req)
}
}

I when I run the client to initiate the trace, I get the error:

rpc error: code = 13 desc = stream terminated by RST_STREAM with error code: 1

I'm confused because I don't see anything else about authentication; only providing the project ID which can't be enough to initiate tracing for a specific project. What am I missing?

答案1

得分: 1

问题出在:

defer span.Finish()

这个调用不会阻塞,所以因为我只是在进行初步测试,只有一个调用,所以在跟踪上传之前,我的程序就退出了。我联系了https://rakyll.org/grpc-trace/的作者,她实际上更新了她的帖子,提供了使用以下选项的方法:

defer span.FinishWait()

它会阻塞,这样在程序退出之前,跟踪就能成功上传了。

此外,对于长时间运行的 Web 服务器,这不会成为问题,因为进程不会被终止。

英文:

The issue was with:

defer span.Finish()

That call does not block so because I was just doing preliminary testing with one call my program was exiting before the traces could be uploaded. I contacted the author of https://rakyll.org/grpc-trace/ and she actually updated her post with the option of using:

defer span.FinishWait()

which blocks and that fixed it by allowing the traces to be successfully uploaded before the program exited.

Also, with a long running webserver this wouldn't have been an issue because the process wouldn't have been terminated.

答案2

得分: 0

我遵循了相同的教程,并遇到了类似的问题。

头部键被转换为小写。如果你在服务器端使用header := strings.Join(md["x-cloud-trace-context"], "")来检索它,应该没问题。

你也可以使用以下方式定义你的元数据头部:

span := trace.FromContext(ctx).NewChild(method)
defer span.Finish()
md := metadata.Pairs(
"x-cloud-trace-context", fmt.Sprintf("%s/%d;o=1", span.TraceID(), 0),
)
ctx = metadata.NewContext(ctx, md)
英文:

I followed those same tutorials and ran into similar problems.

Header keys are converted to lowercase. If you retrieve it on the server side with header := strings.Join(md["x-cloud-trace-context"], "") you should be good.

You can also define your metadata headers with:

span := trace.FromContext(ctx).NewChild(method)
defer span.Finish()
md := metadata.Pairs(
"x-cloud-trace-context", fmt.Sprintf("%s/%d;o=1", span.TraceID(), 0),
)
ctx = metadata.NewContext(ctx, md)

huangapple
  • 本文由 发表于 2017年3月25日 11:11:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/43012091.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定