如何解决将跟踪添加到 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 的跟踪,我看到了上述方法的跟踪:
尽管将 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)
}
}
跟踪现在会进入控制台:
但是,查看跟踪记录,现在(不幸的是??)有两个跟踪条目:
- Cloud Run 提供的默认跟踪(没有子跟踪)
- gRPC 拦截器生成的新跟踪(带有反映内部调用方法的子跟踪)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。