mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 10:03:42 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			142 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			142 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package otgrpc
 | 
						|
 | 
						|
import (
 | 
						|
	"github.com/opentracing/opentracing-go"
 | 
						|
	"github.com/opentracing/opentracing-go/ext"
 | 
						|
	"github.com/opentracing/opentracing-go/log"
 | 
						|
	"golang.org/x/net/context"
 | 
						|
	"google.golang.org/grpc"
 | 
						|
	"google.golang.org/grpc/metadata"
 | 
						|
)
 | 
						|
 | 
						|
// OpenTracingServerInterceptor returns a grpc.UnaryServerInterceptor suitable
 | 
						|
// for use in a grpc.NewServer call.
 | 
						|
//
 | 
						|
// For example:
 | 
						|
//
 | 
						|
//     s := grpc.NewServer(
 | 
						|
//         ...,  // (existing ServerOptions)
 | 
						|
//         grpc.UnaryInterceptor(otgrpc.OpenTracingServerInterceptor(tracer)))
 | 
						|
//
 | 
						|
// All gRPC server spans will look for an OpenTracing SpanContext in the gRPC
 | 
						|
// metadata; if found, the server span will act as the ChildOf that RPC
 | 
						|
// SpanContext.
 | 
						|
//
 | 
						|
// Root or not, the server Span will be embedded in the context.Context for the
 | 
						|
// application-specific gRPC handler(s) to access.
 | 
						|
func OpenTracingServerInterceptor(tracer opentracing.Tracer, optFuncs ...Option) grpc.UnaryServerInterceptor {
 | 
						|
	otgrpcOpts := newOptions()
 | 
						|
	otgrpcOpts.apply(optFuncs...)
 | 
						|
	return func(
 | 
						|
		ctx context.Context,
 | 
						|
		req interface{},
 | 
						|
		info *grpc.UnaryServerInfo,
 | 
						|
		handler grpc.UnaryHandler,
 | 
						|
	) (resp interface{}, err error) {
 | 
						|
		spanContext, err := extractSpanContext(ctx, tracer)
 | 
						|
		if err != nil && err != opentracing.ErrSpanContextNotFound {
 | 
						|
			// TODO: establish some sort of error reporting mechanism here. We
 | 
						|
			// don't know where to put such an error and must rely on Tracer
 | 
						|
			// implementations to do something appropriate for the time being.
 | 
						|
		}
 | 
						|
		if otgrpcOpts.inclusionFunc != nil &&
 | 
						|
			!otgrpcOpts.inclusionFunc(spanContext, info.FullMethod, req, nil) {
 | 
						|
			return handler(ctx, req)
 | 
						|
		}
 | 
						|
		serverSpan := tracer.StartSpan(
 | 
						|
			info.FullMethod,
 | 
						|
			ext.RPCServerOption(spanContext),
 | 
						|
			gRPCComponentTag,
 | 
						|
		)
 | 
						|
		defer serverSpan.Finish()
 | 
						|
 | 
						|
		ctx = opentracing.ContextWithSpan(ctx, serverSpan)
 | 
						|
		if otgrpcOpts.logPayloads {
 | 
						|
			serverSpan.LogFields(log.Object("gRPC request", req))
 | 
						|
		}
 | 
						|
		resp, err = handler(ctx, req)
 | 
						|
		if err == nil {
 | 
						|
			if otgrpcOpts.logPayloads {
 | 
						|
				serverSpan.LogFields(log.Object("gRPC response", resp))
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			SetSpanTags(serverSpan, err, false)
 | 
						|
			serverSpan.LogFields(log.String("event", "error"), log.String("message", err.Error()))
 | 
						|
		}
 | 
						|
		if otgrpcOpts.decorator != nil {
 | 
						|
			otgrpcOpts.decorator(serverSpan, info.FullMethod, req, resp, err)
 | 
						|
		}
 | 
						|
		return resp, err
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// OpenTracingStreamServerInterceptor returns a grpc.StreamServerInterceptor suitable
 | 
						|
// for use in a grpc.NewServer call. The interceptor instruments streaming RPCs by
 | 
						|
// creating a single span to correspond to the lifetime of the RPC's stream.
 | 
						|
//
 | 
						|
// For example:
 | 
						|
//
 | 
						|
//     s := grpc.NewServer(
 | 
						|
//         ...,  // (existing ServerOptions)
 | 
						|
//         grpc.StreamInterceptor(otgrpc.OpenTracingStreamServerInterceptor(tracer)))
 | 
						|
//
 | 
						|
// All gRPC server spans will look for an OpenTracing SpanContext in the gRPC
 | 
						|
// metadata; if found, the server span will act as the ChildOf that RPC
 | 
						|
// SpanContext.
 | 
						|
//
 | 
						|
// Root or not, the server Span will be embedded in the context.Context for the
 | 
						|
// application-specific gRPC handler(s) to access.
 | 
						|
func OpenTracingStreamServerInterceptor(tracer opentracing.Tracer, optFuncs ...Option) grpc.StreamServerInterceptor {
 | 
						|
	otgrpcOpts := newOptions()
 | 
						|
	otgrpcOpts.apply(optFuncs...)
 | 
						|
	return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
 | 
						|
		spanContext, err := extractSpanContext(ss.Context(), tracer)
 | 
						|
		if err != nil && err != opentracing.ErrSpanContextNotFound {
 | 
						|
			// TODO: establish some sort of error reporting mechanism here. We
 | 
						|
			// don't know where to put such an error and must rely on Tracer
 | 
						|
			// implementations to do something appropriate for the time being.
 | 
						|
		}
 | 
						|
		if otgrpcOpts.inclusionFunc != nil &&
 | 
						|
			!otgrpcOpts.inclusionFunc(spanContext, info.FullMethod, nil, nil) {
 | 
						|
			return handler(srv, ss)
 | 
						|
		}
 | 
						|
 | 
						|
		serverSpan := tracer.StartSpan(
 | 
						|
			info.FullMethod,
 | 
						|
			ext.RPCServerOption(spanContext),
 | 
						|
			gRPCComponentTag,
 | 
						|
		)
 | 
						|
		defer serverSpan.Finish()
 | 
						|
		ss = &openTracingServerStream{
 | 
						|
			ServerStream: ss,
 | 
						|
			ctx:          opentracing.ContextWithSpan(ss.Context(), serverSpan),
 | 
						|
		}
 | 
						|
		err = handler(srv, ss)
 | 
						|
		if err != nil {
 | 
						|
			SetSpanTags(serverSpan, err, false)
 | 
						|
			serverSpan.LogFields(log.String("event", "error"), log.String("message", err.Error()))
 | 
						|
		}
 | 
						|
		if otgrpcOpts.decorator != nil {
 | 
						|
			otgrpcOpts.decorator(serverSpan, info.FullMethod, nil, nil, err)
 | 
						|
		}
 | 
						|
		return err
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
type openTracingServerStream struct {
 | 
						|
	grpc.ServerStream
 | 
						|
	ctx context.Context
 | 
						|
}
 | 
						|
 | 
						|
func (ss *openTracingServerStream) Context() context.Context {
 | 
						|
	return ss.ctx
 | 
						|
}
 | 
						|
 | 
						|
func extractSpanContext(ctx context.Context, tracer opentracing.Tracer) (opentracing.SpanContext, error) {
 | 
						|
	md, ok := metadata.FromIncomingContext(ctx)
 | 
						|
	if !ok {
 | 
						|
		md = metadata.New(nil)
 | 
						|
	}
 | 
						|
	return tracer.Extract(opentracing.HTTPHeaders, metadataReaderWriter{md})
 | 
						|
}
 |