code: func StreamServerInterceptor(entry *logrus.Entry, opts ...Option) grpc.StreamServerInterceptor {
  	o := evaluateServerOpt(opts)
  	return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
  		startTime := time.Now()
  		newCtx := newLoggerForCall(stream.Context(), entry, info.FullMethod, startTime)
  		wrapped := grpc_middleware.WrapServerStream(stream)
  		wrapped.WrappedContext = newCtx
  
  		err := handler(srv, wrapped)
  
  		if !o.shouldLog(info.FullMethod, err) {
  			return err
  		}
  		code := o.codeFunc(err)
  		level := o.levelFunc(code)
  		durField, durVal := o.durationFunc(time.Since(startTime))
  		fields := logrus.Fields{
  			"grpc.code": code.String(),
  			durField:    durVal,
  		}
  		if err != nil {
  			fields[logrus.ErrorKey] = err
  		}
  
  		levelLogf(
  			ctx_logrus.Extract(newCtx).WithFields(fields), // re-extract logger from newCtx, as it may have extra fields that changed in the holder.
  			level,
  			"finished streaming call with code "+code.String())
  
  		return err
  	}
  }
docs: // StreamServerInterceptor returns a new streaming server interceptor that adds logrus.Entry to the context.