go-grpc-middleware icon indicating copy to clipboard operation
go-grpc-middleware copied to clipboard

The execution order of otelgrpc.StreamClientInterceptor() and otelgrpc.NewClientHandler() has changed.

Open b-anastasiia opened this issue 9 months ago • 1 comments

After otelgrpc.StreamClientInterceptor() was deprecated, it is recommended to replace it with otelgrpc.NewClientHandler().

However, the execution order is different: interceptors run first, followed by StatsHandlers. From the code, this seems to be the intended behavior. But how should one proceed if it’s necessary for the trace_id and span_id fields to appear in the logs?

Before (logs with traicing fields):

    func SpanContextFields(ctx context.Context) logging.Fields {
        if spanCtx := trace.SpanContextFromContext(ctx); spanCtx.IsSampled() {
            return logging.Fields{
                traceIDKey, spanCtx.TraceID().String(),
                spanIDKey, spanCtx.SpanID().String(),
            }
         }

         return nil
     }

    streamInterceptors := []grpc.StreamClientInterceptor{
        otelgrpc.StreamClientInterceptor(),
        logging.StreamClientInterceptor(
            logger.GRPCLogger(zap.L()),
            logging.WithLevels(logger.GRPCClientCodeToLevel),
            logging.WithFieldsFromContext(logger.SpanContextFields),
        ),
     }
	
    return grpc.NewClient(
        target,
        grpc.WithTransportCredentials(insecure.NewCredentials()),
        grpc.WithChainUnaryInterceptor(append(unaryInterceptors, o.unaryInterceptors...)...),
        grpc.WithChainStreamInterceptor(append(streamInterceptors, o.streamInterceptors...)...),
     )

Now (logs without traicing fields):

    func SpanContextFields(ctx context.Context) logging.Fields {
        if spanCtx := trace.SpanContextFromContext(ctx); spanCtx.IsSampled() {
            return logging.Fields{
                traceIDKey, spanCtx.TraceID().String(),
                spanIDKey, spanCtx.SpanID().String(),
            }
         }

         return nil
     }

    streamInterceptors := []grpc.StreamClientInterceptor{
        logging.StreamClientInterceptor(
            logger.GRPCLogger(zap.L()),
            logging.WithLevels(logger.GRPCClientCodeToLevel),
            logging.WithFieldsFromContext(logger.SpanContextFields),
        ),
    }
	
    return grpc.NewClient(
        target,
        grpc.WithTransportCredentials(insecure.NewCredentials()),
        grpc.WithStatsHandler(otelgrpc.NewClientHandler()),
        grpc.WithChainUnaryInterceptor(append(unaryInterceptors, o.unaryInterceptors...)...),
        grpc.WithChainStreamInterceptor(append(streamInterceptors, o.streamInterceptors...)...),
     )

b-anastasiia avatar Jan 16 '25 07:01 b-anastasiia