微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将跟踪添加到 Cloud Run 中的内部方法

如何解决将跟踪添加到 Cloud Run 中的内部方法

我们希望为 Cloud Run 上部署的服务中使用的方法添加跟踪。

跟踪已提供的 Cloud Run 请求:


假设我们有以下 gRPC 方法

func (s *myServiceService) SyncTable(ctx context.Context,req *pb.SyncTableRequest) (*longrunning.Operation,error) {

    //.... some stuff here...
    
    // making a call to the internal method,which has a tracing span
    err := dropRequestOnStorage(ctx,...)
    if err != nil {
        return nil,err
    }
    
    return op,nil
}

以下是一个内部方法示例,我们向该方法添加了 Trace span 并由主 gRPC 方法调用

// dropRequestOnStorage loads the requests on the relevant bucket.
func dropRequestOnStorage(ctx context.Context,filename string,operationID string,req *pb.ExtractDataRequest) error {
 
    // add tracing to this method.
    ctx,span := otel.Tracer("").Start(ctx,"dropRequestOnStorage")
    defer span.End()

    // load json object to storage
    reqByte,err := protojson.Marshal(req)
    if err != nil {
        fmt.Println(err)
    }
    wc := storageClient.Bucket("my-bucket-with-cool-stuff").Object(filename).NewWriter(ctx)
    wc.ContentType = "application/json"
    
    _,err = wc.Write(reqByte)
    if err != nil {
        fmt.Println(err)
    }
    wc.Close()
    fmt.Println(filename)
    return nil
}

查看 Google Cloud Run 的跟踪,我看到了上述方法的跟踪:

Google Cloud Run tracing

尽管将 context 从主 gRPC 传递到内部方法,但不会将 Tracing 拉到底层内部。内部方法生成的跟踪不会“接收”作为父级的主 gRPC 跟踪。

这是因为 Cloud Run 提供的认跟踪是由 Cloud Run 内部完成的吗?因此不适用于 gRPC 方法的上下文?

解决方法

使用 gRPC 拦截器进行跟踪


实现此功能的唯一方法是添加 gRPC 拦截器来为每个 gRPC 方法创建跟踪范围。

package main

import (
    "context"
    texporter "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace"
    "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/propagation"
    sdktrace "go.opentelemetry.io/otel/sdk/trace"
    "google.golang.org/grpc"
    "log"
    "net"
    "os"
)

func init() {

    // Pre-declare err to avoid shadowing.
    var err error

    // initialising tracing exporter
    //exporter,err := stdout.NewExporter(stdout.WithPrettyPrint())
    exporter,err := texporter.NewExporter(texporter.WithProjectID("alis-de"))
    if err != nil {
        log.Fatalf("texporter.NewExporter: %v",err)
    }

    tp := sdktrace.NewTracerProvider(
        sdktrace.WithSampler(sdktrace.AlwaysSample()),sdktrace.WithSyncer(exporter),)

    otel.SetTracerProvider(tp)
    otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{},propagation.Baggage{}))
}

func main() {
    log.Printf("starting server...")
    
    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
        log.Printf("Defaulting to port %s",port)
    }

    listener,err := net.Listen("tcp",":"+port)
    if err != nil {
        log.Fatalf("net.Listen: %v",err)
    }
    
    // Attaching grpc interceptors to automatically enable tracing at gRCP methods
    grpcServer := grpc.NewServer(
        grpc.UnaryInterceptor(otelgrpc.UnaryServerInterceptor()),grpc.StreamInterceptor(otelgrpc.StreamServerInterceptor()),)

    pb.RegisterOperationsServer(grpcServer,&operationsService{})

    if err = grpcServer.Serve(listener); err != nil {
        log.Fatal(err)
    }
}

跟踪现在会进入控制台:

Tracing using gRPC Interceptors

但是,查看跟踪记录,现在(不幸的是??)有两个跟踪条目:

  1. Cloud Run 提供的默认跟踪(没有子跟踪)
  2. gRPC 拦截器生成的新跟踪(带有反映内部调用方法的子跟踪)

Duplicate trace entries

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。