/// <summary>
 /// Initializes a new instance of the <see cref="ClientTracingInterceptor"/> class.
 /// </summary>
 /// <param name="options">The options.</param>
 public ClientTracingInterceptor(ClientTracingInterceptorOptions options)
 {
     this.options = options ?? throw new ArgumentNullException(nameof(options));
 }
            /// <summary>
            /// Initializes a new instance of the <see cref="ClientRpcScope{TRequest, TResponse}" /> class.
            /// </summary>
            /// <param name="context">The context.</param>
            /// <param name="options">The options.</param>
            public ClientRpcScope(ClientInterceptorContext <TRequest, TResponse> context, ClientTracingInterceptorOptions options)
                : base(context.Method?.FullName, options.RecordMessageEvents)
            {
                this.context = context;

                // Capture the current activity.
                this.parentActivity = Activity.Current;

                // Short-circuit if nobody is listening
                if (!GrpcCoreInstrumentation.ActivitySource.HasListeners())
                {
                    return;
                }

                // This if block is for unit testing only.
                IEnumerable <KeyValuePair <string, object> > customTags = null;

                if (options.ActivityIdentifierValue != default)
                {
                    customTags = new List <KeyValuePair <string, object> >
                    {
                        new KeyValuePair <string, object>(SemanticConventions.AttributeActivityIdentifier, options.ActivityIdentifierValue),
                    };
                }

                // We want to start an activity but don't activate it.
                // After calling StartActivity, Activity.Current will be the new Activity.
                // This scope is created synchronously before the RPC invocation starts and so this new Activity will overwrite
                // the callers current Activity which isn't what we want. We need to restore the original immediately after doing this.
                // If this call happened after some kind of async context await then a restore wouldn't be necessary.
                // gRPC Core just doesn't have the hooks to do this as far as I can tell.
                var rpcActivity = GrpcCoreInstrumentation.ActivitySource.StartActivity(
                    this.FullServiceName,
                    ActivityKind.Client,
                    this.parentActivity == default ? default : this.parentActivity.Context,
                    tags: customTags);

                if (rpcActivity == null)
                {
                    return;
                }

                var callOptions = context.Options;

                // Do NOT mutate incoming call headers, make a new copy.
                // Retry mechanisms that may sit above this interceptor rely on an original set of call headers.
                var metadata = new Metadata();

                if (callOptions.Headers != null)
                {
                    for (var i = 0; i < callOptions.Headers.Count; i++)
                    {
                        metadata.Add(callOptions.Headers[i]);
                    }
                }

                // replace the CallOptions
                callOptions = callOptions.WithHeaders(metadata);

                this.SetActivity(rpcActivity);
                options.Propagator.Inject(new PropagationContext(rpcActivity.Context, Baggage.Current), callOptions.Headers, MetadataSetter);
                this.context = new ClientInterceptorContext <TRequest, TResponse>(context.Method, context.Host, callOptions);
            }