public async Task ExtractContextIrrespectiveOfSamplingDecision(SamplingDecision samplingDecision)
        {
            try
            {
                var expectedTraceId      = ActivityTraceId.CreateRandom();
                var expectedParentSpanId = ActivitySpanId.CreateRandom();
                var expectedTraceState   = "rojo=1,congo=2";
                var activityContext      = new ActivityContext(expectedTraceId, expectedParentSpanId, ActivityTraceFlags.Recorded, expectedTraceState);
                var expectedBaggage      = Baggage.SetBaggage("key1", "value1").SetBaggage("key2", "value2");
                OpenTelemetrySdk.SetDefaultTextMapPropagator(new ExtractOnlyPropagator(activityContext, expectedBaggage));

                // Arrange
                using (var testFactory = this.factory
                                         .WithWebHostBuilder(builder =>
                                                             builder.ConfigureTestServices(services =>
                {
                    this.openTelemetrySdk = OpenTelemetrySdk.CreateTracerProviderBuilder()
                                            .SetSampler(new TestSampler(samplingDecision))
                                            .AddAspNetCoreInstrumentation()
                                            .Build();
                })))
                {
                    using var client = testFactory.CreateClient();

                    // Test TraceContext Propagation
                    var request  = new HttpRequestMessage(HttpMethod.Get, "/api/GetChildActivityTraceContext");
                    var response = await client.SendAsync(request);

                    var childActivityTraceContext = JsonConvert.DeserializeObject <Dictionary <string, string> >(response.Content.ReadAsStringAsync().Result);

                    response.EnsureSuccessStatusCode();

                    Assert.Equal(expectedTraceId.ToString(), childActivityTraceContext["TraceId"]);
                    Assert.Equal(expectedTraceState, childActivityTraceContext["TraceState"]);
                    Assert.NotEqual(expectedParentSpanId.ToString(), childActivityTraceContext["ParentSpanId"]); // there is a new activity created in instrumentation therefore the ParentSpanId is different that what is provided in the headers

                    // Test Baggage Context Propagation
                    request = new HttpRequestMessage(HttpMethod.Get, "/api/GetChildActivityBaggageContext");

                    response = await client.SendAsync(request);

                    var childActivityBaggageContext = JsonConvert.DeserializeObject <IReadOnlyDictionary <string, string> >(response.Content.ReadAsStringAsync().Result);

                    response.EnsureSuccessStatusCode();

                    Assert.Single(childActivityBaggageContext, item => item.Key == "key1" && item.Value == "value1");
                    Assert.Single(childActivityBaggageContext, item => item.Key == "key2" && item.Value == "value2");
                }
            }
            finally
            {
                OpenTelemetrySdk.SetDefaultTextMapPropagator(new CompositeTextMapPropagator(new TextMapPropagator[]
                {
                    new TraceContextPropagator(),
                    new BaggagePropagator(),
                }));
            }
        }
        public void GrpcAspNetCoreInstrumentationAddsCorrectAttributesWhenItCreatesNewActivity(bool?enableGrpcAspNetCoreSupport)
        {
            try
            {
                // B3Propagator along with the headers passed to the client.SayHello ensure that the instrumentation creates a sibling activity
                OpenTelemetrySdk.SetDefaultTextMapPropagator(new B3Propagator());
                var processor             = new Mock <BaseProcessor <Activity> >();
                var tracerProviderBuilder = OpenTelemetrySdk.CreateTracerProviderBuilder();

                if (enableGrpcAspNetCoreSupport.HasValue)
                {
                    tracerProviderBuilder.AddAspNetCoreInstrumentation(options =>
                    {
                        options.EnableGrpcAspNetCoreSupport = enableGrpcAspNetCoreSupport.Value;
                    });
                }
                else
                {
                    tracerProviderBuilder.AddAspNetCoreInstrumentation();
                }

                using var tracerProvider = tracerProviderBuilder
                                           .AddProcessor(processor.Object)
                                           .Build();

                var clientLoopbackAddresses = new[] { IPAddress.Loopback.ToString(), IPAddress.IPv6Loopback.ToString() };
                var uri = new Uri($"http://localhost:{this.server.Port}");

                using var channel = GrpcChannel.ForAddress(uri);
                var client  = new Greeter.GreeterClient(channel);
                var headers = new Metadata();
                headers.Add("traceparent", "00-120dc44db5b736468afb112197b0dbd3-5dfbdf27ec544544-01");
                headers.Add("x-b3-traceid", "120dc44db5b736468afb112197b0dbd3");
                headers.Add("x-b3-spanid", "b0966f651b9e0126");
                headers.Add("x-b3-sampled", "1");
                client.SayHello(new HelloRequest(), headers);

                WaitForProcessorInvocations(processor, 4);

                Assert.Equal(4, processor.Invocations.Count); // SetParentProvider, OnStart (framework activity), OnStart (instrumentation activity), OnStop (instrumentation activity)
                var activity = GetActivityFromProcessorInvocation(processor, nameof(processor.Object.OnEnd), OperationNameHttpRequestIn);

                Assert.Equal(ActivityKind.Server, activity.Kind);

                if (!enableGrpcAspNetCoreSupport.HasValue || enableGrpcAspNetCoreSupport.Value)
                {
                    Assert.Equal("grpc", activity.GetTagValue(SemanticConventions.AttributeRpcSystem));
                    Assert.Equal("greet.Greeter", activity.GetTagValue(SemanticConventions.AttributeRpcService));
                    Assert.Equal("SayHello", activity.GetTagValue(SemanticConventions.AttributeRpcMethod));
                    Assert.Contains(activity.GetTagValue(SemanticConventions.AttributeNetPeerIp), clientLoopbackAddresses);
                    Assert.NotEqual(0, activity.GetTagValue(SemanticConventions.AttributeNetPeerPort));
                    Assert.Null(activity.GetTagValue(GrpcTagHelper.GrpcMethodTagName));
                    Assert.Null(activity.GetTagValue(GrpcTagHelper.GrpcStatusCodeTagName));
                    Assert.Equal(0, activity.GetTagValue(SemanticConventions.AttributeRpcGrpcStatusCode));
                }
                else
                {
                    Assert.NotNull(activity.GetTagValue(GrpcTagHelper.GrpcMethodTagName));
                    Assert.NotNull(activity.GetTagValue(GrpcTagHelper.GrpcStatusCodeTagName));
                }

                Assert.Equal(Status.Unset, activity.GetStatus());

                // The following are http.* attributes that are also included on the span for the gRPC invocation.
                Assert.Equal($"localhost:{this.server.Port}", activity.GetTagValue(SemanticConventions.AttributeHttpHost));
                Assert.Equal("POST", activity.GetTagValue(SemanticConventions.AttributeHttpMethod));
                Assert.Equal("/greet.Greeter/SayHello", activity.GetTagValue(SpanAttributeConstants.HttpPathKey));
                Assert.Equal($"http://localhost:{this.server.Port}/greet.Greeter/SayHello", activity.GetTagValue(SemanticConventions.AttributeHttpUrl));
                Assert.StartsWith("grpc-dotnet", activity.GetTagValue(SemanticConventions.AttributeHttpUserAgent) as string);
            }
            finally
            {
                // Set the SDK to use the default propagator for other unit tests
                OpenTelemetrySdk.SetDefaultTextMapPropagator(new CompositeTextMapPropagator(new TextMapPropagator[]
                {
                    new TraceContextPropagator(),
                    new BaggagePropagator(),
                }));
            }
        }
        public async Task CustomPropagator()
        {
            try
            {
                var activityProcessor = new Mock <BaseProcessor <Activity> >();

                var expectedTraceId = ActivityTraceId.CreateRandom();
                var expectedSpanId  = ActivitySpanId.CreateRandom();

                var propagator = new Mock <TextMapPropagator>();
                propagator.Setup(m => m.Extract(It.IsAny <PropagationContext>(), It.IsAny <HttpRequest>(), It.IsAny <Func <HttpRequest, string, IEnumerable <string> > >())).Returns(
                    new PropagationContext(
                        new ActivityContext(
                            expectedTraceId,
                            expectedSpanId,
                            ActivityTraceFlags.Recorded),
                        default));

                // Arrange
                using (var testFactory = this.factory
                                         .WithWebHostBuilder(builder =>
                                                             builder.ConfigureTestServices(services =>
                {
                    OpenTelemetrySdk.SetDefaultTextMapPropagator(propagator.Object);
                    this.openTelemetrySdk = OpenTelemetrySdk.CreateTracerProviderBuilder()
                                            .AddAspNetCoreInstrumentation()
                                            .AddProcessor(activityProcessor.Object)
                                            .Build();
                })))
                {
                    using var client = testFactory.CreateClient();
                    var response = await client.GetAsync("/api/values/2");

                    response.EnsureSuccessStatusCode(); // Status Code 200-299

                    WaitForProcessorInvocations(activityProcessor, 4);
                }

                // List of invocations on the processor
                // 1. SetParentProvider for TracerProviderSdk
                // 2. OnStart for the activity created by AspNetCore with the OperationName: Microsoft.AspNetCore.Hosting.HttpRequestIn
                // 3. OnStart for the sibling activity created by the instrumentation library with the OperationName: Microsoft.AspNetCore.Hosting.HttpRequestIn and the first tag that is added is (IsCreatedByInstrumentation, bool.TrueString)
                // 4. OnEnd for the sibling activity created by the instrumentation library with the OperationName: Microsoft.AspNetCore.Hosting.HttpRequestIn and the first tag that is added is (IsCreatedByInstrumentation, bool.TrueString)
                Assert.Equal(4, activityProcessor.Invocations.Count);

                var startedActivities = activityProcessor.Invocations.Where(invo => invo.Method.Name == "OnStart");
                var stoppedActivities = activityProcessor.Invocations.Where(invo => invo.Method.Name == "OnEnd");
                Assert.Equal(2, startedActivities.Count());
                Assert.Single(stoppedActivities);

                // The activity created by the framework and the sibling activity are both sent to Processor.OnStart
                Assert.Equal(2, startedActivities.Count(item =>
                {
                    var startedActivity = item.Arguments[0] as Activity;
                    return(startedActivity.OperationName == HttpInListener.ActivityOperationName);
                }));

                // we should only call Processor.OnEnd once for the sibling activity
                Assert.Single(activityProcessor.Invocations, invo => invo.Method.Name == "OnEnd");

                var activity = activityProcessor.Invocations.FirstOrDefault(invo => invo.Method.Name == "OnEnd").Arguments[0] as Activity;
                Assert.True(activity.Duration != TimeSpan.Zero);
                Assert.Equal("api/Values/{id}", activity.DisplayName);

                Assert.Equal(expectedTraceId, activity.Context.TraceId);
                Assert.Equal(expectedSpanId, activity.ParentSpanId);

                ValidateAspNetCoreActivity(activity, "/api/values/2");
            }
            finally
            {
                OpenTelemetrySdk.SetDefaultTextMapPropagator(new CompositeTextMapPropagator(new TextMapPropagator[]
                {
                    new TraceContextPropagator(),
                    new BaggagePropagator(),
                }));
            }
        }