gRPC - GoLang - трассировщик Stackdriver

Я пытаюсь заставить трассировщик stackdriver работать с gRPC, и мне нужна помощь. Я просматривал эти две ссылки для справки, но все еще не могу заставить их работать:

Для простоты я просто работаю с примером 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

Я сбит с толку, потому что больше ничего не вижу об аутентификации; предоставление только идентификатора проекта, которого недостаточно для запуска трассировки для конкретного проекта. Что мне не хватает?


person jrkt    schedule 25.03.2017    source источник
comment
Что вы видели и что ожидали увидеть? Ваш вопрос расплывчатый.   -  person Kenny Grant    schedule 25.03.2017
comment
Я ожидаю увидеть следы на странице трассировки stackdriver моего проекта, но не вижу их.   -  person jrkt    schedule 25.03.2017
comment
Можете ли вы исправить это с помощью ответа, приведенного ниже?   -  person JL-HaiNan    schedule 25.04.2017


Ответы (2)


Проблема заключалась в следующем:

defer span.Finish()

Этот вызов не блокируется, потому что я просто проводил предварительное тестирование с одним вызовом, из которого моя программа выходила до того, как можно было загрузить трассировки. Я связался с автором https://rakyll.org/grpc-trace/, и она действительно обновила ее сообщение с возможностью использования:

defer span.FinishWait()

который блокирует и исправляет это, разрешая успешную загрузку трассировок до выхода из программы.

Кроме того, с долго работающим веб-сервером это не было бы проблемой, потому что процесс не был бы остановлен.

person jrkt    schedule 25.04.2017

Я последовал тем же инструкциям и столкнулся с аналогичными проблемами.

Ключи заголовка преобразуются в нижний регистр. Если вы получите его на стороне сервера с помощью 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)
person stu    schedule 14.04.2017