gRPC - GoLang - Stackdriver 追踪器
gRPC - GoLang - Stackdriver tracer
我正在尝试获取 stackdriver tracer to work with gRPC,我需要一些帮助。我一直在查看这两个链接以供参考,但我仍然无法正常工作:
- https://medium.com/@harlow/tracing-grpc-calls-in-golang-with-google-stackdriver-b22495763a06#.81oa9q21v
- https://rakyll.org/grpc-trace/
为简单起见,我只使用 hello world gRPC example。这是我的客户:
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 不足以启动对特定项目的跟踪。我错过了什么?
我按照相同的教程 运行 解决了类似的问题。
Header 键被转换为小写。如果您使用 header := strings.Join(md["x-cloud-trace-context"], "")
在服务器端检索它,您应该没问题。
您还可以定义元数据 headers:
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)
问题在于:
defer span.Finish()
该调用不会阻塞,因为我只是用一个调用进行初步测试,我的程序在跟踪可以上传之前退出。我联系了 https://rakyll.org/grpc-trace/ 的作者,她实际上更新了她的 post 使用选项:
defer span.FinishWait()
通过在程序退出之前允许成功上传跟踪来阻止和修复它。
此外,对于长 运行 网络服务器,这不会成为问题,因为进程不会终止。
我正在尝试获取 stackdriver tracer to work with gRPC,我需要一些帮助。我一直在查看这两个链接以供参考,但我仍然无法正常工作:
- https://medium.com/@harlow/tracing-grpc-calls-in-golang-with-google-stackdriver-b22495763a06#.81oa9q21v
- https://rakyll.org/grpc-trace/
为简单起见,我只使用 hello world gRPC example。这是我的客户:
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 不足以启动对特定项目的跟踪。我错过了什么?
我按照相同的教程 运行 解决了类似的问题。
Header 键被转换为小写。如果您使用 header := strings.Join(md["x-cloud-trace-context"], "")
在服务器端检索它,您应该没问题。
您还可以定义元数据 headers:
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)
问题在于:
defer span.Finish()
该调用不会阻塞,因为我只是用一个调用进行初步测试,我的程序在跟踪可以上传之前退出。我联系了 https://rakyll.org/grpc-trace/ 的作者,她实际上更新了她的 post 使用选项:
defer span.FinishWait()
通过在程序退出之前允许成功上传跟踪来阻止和修复它。
此外,对于长 运行 网络服务器,这不会成为问题,因为进程不会终止。