Exemple #1
0
        public void TracerProviderSdkSamplerAttributesAreAppliedToActivity(SamplingDecision sampling)
        {
            var testSampler = new TestSampler();

            testSampler.SamplingAction = (samplingParams) =>
            {
                var attributes = new Dictionary <string, object>();
                attributes.Add("tagkeybysampler", "tagvalueaddedbysampler");
                return(new SamplingResult(sampling, attributes));
            };

            using var activitySource = new ActivitySource(ActivitySourceName);
            using var sdk            = Sdk.CreateTracerProviderBuilder()
                                       .AddSource(ActivitySourceName)
                                       .SetSampler(testSampler)
                                       .Build();

            using (var rootActivity = activitySource.StartActivity("root"))
            {
                Assert.NotNull(rootActivity);
                Assert.Equal(rootActivity.TraceId, testSampler.LatestSamplingParameters.TraceId);
                if (sampling != SamplingDecision.Drop)
                {
                    Assert.Contains(new KeyValuePair <string, object>("tagkeybysampler", "tagvalueaddedbysampler"), rootActivity.TagObjects);
                }
            }
        }
Exemple #2
0
        public void SdkSamplesLegacyActivityWithCustomSampler(SamplingDecision samplingDecision, bool isAllDataRequested, bool hasRecordedFlag)
        {
            var operationNameForLegacyActivity = "TestOperationName";
            var sampler = new TestSampler()
            {
                SamplingAction = (samplingParameters) => new SamplingResult(samplingDecision)
            };

            using var tracerProvider = Sdk.CreateTracerProviderBuilder()
                                       .SetSampler(sampler)
                                       .AddLegacySource(operationNameForLegacyActivity)
                                       .Build();

            Activity activity = new Activity(operationNameForLegacyActivity);

            activity.Start();

            Assert.Equal(isAllDataRequested, activity.IsAllDataRequested);
            Assert.Equal(hasRecordedFlag, activity.ActivityTraceFlags.HasFlag(ActivityTraceFlags.Recorded));

            // Validating ActivityTraceFlags is not enough as it does not get reflected on
            // Id, If the Id is accessed before the sampler runs.
            // https://github.com/open-telemetry/opentelemetry-dotnet/issues/2700
            Assert.EndsWith(hasRecordedFlag ? "-01" : "-00", activity.Id);

            activity.Stop();
        }
Exemple #3
0
        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");
                Sdk.SetDefaultTextMapPropagator(new ExtractOnlyPropagator(activityContext, expectedBaggage));

                // Arrange
                using (var testFactory = this.factory
                                         .WithWebHostBuilder(builder =>
                                                             builder.ConfigureTestServices(services =>
                {
                    this.tracerProvider = Sdk.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
            {
                Sdk.SetDefaultTextMapPropagator(new CompositeTextMapPropagator(new TextMapPropagator[]
                {
                    new TraceContextPropagator(),
                    new BaggagePropagator(),
                }));
            }
        }
Exemple #4
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SamplingResult"/> struct.
        /// </summary>
        /// <param name="decision">indicates whether an activity object is recorded and sampled.</param>
        /// <param name="attributes">Attributes associated with the sampling decision. Attributes list passed to
        /// this method must be immutable. Mutations of the collection and/or attribute values may lead to unexpected behavior.</param>
        public SamplingResult(SamplingDecision decision, IEnumerable <KeyValuePair <string, object> > attributes)
        {
            this.Decision = decision;

            // Note: Decision object takes ownership of the collection.
            // Current implementation has no means to ensure the collection will not be modified by the caller.
            // If this behavior will be abused we must switch to cloning of the collection.
            this.Attributes = attributes;
        }
        public void ActivitySourceAdapterPopulatesSamplingAttributesToActivity(SamplingDecision sampling)
        {
            this.testSampler.SamplingAction = (samplingParams) =>
            {
                var attributes = new Dictionary <string, object>();
                attributes.Add("tagkeybysampler", "tagvalueaddedbysampler");
                return(new SamplingResult(sampling, attributes));
            };

            var activity = new Activity("test");

            activity.Start();
            this.activitySourceAdapter.Start(activity, ActivityKind.Internal);
            if (sampling != SamplingDecision.Drop)
            {
                Assert.Contains(new KeyValuePair <string, object>("tagkeybysampler", "tagvalueaddedbysampler"), activity.TagObjects);
            }

            activity.Stop();
        }
        public void ActivitySourceAdapterCallsStartStopActivityProcessor1(SamplingDecision decision)
        {
            this.testSampler.SamplingAction = (samplingParameters) =>
            {
                return(new SamplingResult(decision));
            };

            bool startCalled = false;
            bool endCalled   = false;

            this.testProcessor.StartAction =
                (a) =>
            {
                startCalled = true;

                // If start is called, that means activity is sampled,
                // and TraceFlag is set to Recorded.
                Assert.Equal(decision == SamplingDecision.Record || decision == SamplingDecision.RecordAndSampled, a.IsAllDataRequested);
                Assert.Equal(decision == SamplingDecision.RecordAndSampled ? ActivityTraceFlags.Recorded : ActivityTraceFlags.None, a.ActivityTraceFlags);
                Assert.Equal(decision == SamplingDecision.RecordAndSampled, a.Recorded);
            };

            this.testProcessor.EndAction =
                (a) =>
            {
                endCalled = true;
            };

            var activity = new Activity("test");

            activity.Start();
            this.activitySourceAdapter.Start(activity, ActivityKind.Producer);
            activity.Stop();
            this.activitySourceAdapter.Stop(activity);

            Assert.Equal(ActivityKind.Producer, activity.Kind);
            Assert.Equal(activity.IsAllDataRequested, startCalled);
            Assert.Equal(activity.IsAllDataRequested, endCalled);
        }
Exemple #7
0
        public void SdkSamplesLegacyActivityWithCustomSampler(SamplingDecision samplingDecision, bool isAllDataRequested, bool hasRecordedFlag)
        {
            var operationNameForLegacyActivity = "TestOperationName";
            var sampler = new TestSampler()
            {
                SamplingAction = (samplingParameters) => new SamplingResult(samplingDecision)
            };

            using var tracerProvider = Sdk.CreateTracerProviderBuilder()
                                       .SetSampler(sampler)
                                       .AddLegacySource(operationNameForLegacyActivity)
                                       .Build();

            Activity activity = new Activity(operationNameForLegacyActivity);

            activity.Start();

            Assert.Equal(isAllDataRequested, activity.IsAllDataRequested);
            Assert.Equal(hasRecordedFlag, activity.ActivityTraceFlags.HasFlag(ActivityTraceFlags.Recorded));

            activity.Stop();
        }
Exemple #8
0
        public async Task ShouldMapMassTransitTagsWhenIntrumentationWhenSampled(SamplingDecision samplingDecision, bool isActivityExpected)
        {
            var activityProcessor = new Mock <BaseProcessor <Activity> >();

            using (Sdk.CreateTracerProviderBuilder()
                   .SetSampler(new TestSampler()
            {
                SamplingAction = (samplingParameters) => new SamplingResult(samplingDecision)
            })
                   .AddProcessor(activityProcessor.Object)
                   .AddMassTransitInstrumentation()
                   .Build())
            {
                var harness         = new InMemoryTestHarness();
                var consumerHarness = harness.Consumer <TestConsumer>();
                var handlerHarness  = harness.Handler <TestMessage>();
                await harness.Start();

                try
                {
                    await harness.InputQueueSendEndpoint.Send <TestMessage>(new { Text = "Hello, world!" });

                    Assert.True(await harness.Consumed.SelectAsync <TestMessage>().Any());
                    Assert.True(await consumerHarness.Consumed.SelectAsync <TestMessage>().Any());
                    Assert.True(await handlerHarness.Consumed.SelectAsync().Any());
                }
                finally
                {
                    await harness.Stop();
                }

                var expectedMessageContext = harness.Sent.Select <TestMessage>().FirstOrDefault()?.Context;
                Assert.NotNull(expectedMessageContext);
            }

            Assert.Equal(isActivityExpected, activityProcessor.Invocations.Any(invo => invo.Method.Name == nameof(activityProcessor.Object.OnStart)));
            Assert.Equal(isActivityExpected, activityProcessor.Invocations.Any(invo => invo.Method.Name == nameof(activityProcessor.Object.OnEnd)));
        }
Exemple #9
0
        public async Task FilterAndEnrichAreOnlyCalledWhenSampled(SamplingDecision samplingDecision, bool shouldFilterBeCalled, bool shouldEnrichBeCalled)
        {
            bool filterCalled = false;
            bool enrichCalled = false;

            void ConfigureTestServices(IServiceCollection services)
            {
                this.tracerProvider = Sdk.CreateTracerProviderBuilder()
                                      .SetSampler(new TestSampler(samplingDecision))
                                      .AddAspNetCoreInstrumentation(options =>
                {
                    options.Filter = (context) =>
                    {
                        filterCalled = true;
                        return(true);
                    };
                    options.Enrich = (activity, methodName, request) =>
                    {
                        enrichCalled = true;
                    };
                })
                                      .Build();
            }

            // Arrange
            using var client = this.factory
                               .WithWebHostBuilder(builder =>
                                                   builder.ConfigureTestServices(ConfigureTestServices))
                               .CreateClient();

            // Act
            var response = await client.GetAsync("/api/values");

            // Assert
            Assert.Equal(shouldFilterBeCalled, filterCalled);
            Assert.Equal(shouldEnrichBeCalled, enrichCalled);
        }
 public TestSampler(SamplingDecision samplingDecision)
 {
     this.samplingDecision = samplingDecision;
 }
Exemple #11
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SamplingResult"/> struct.
 /// </summary>
 /// <param name="decision"> indicates whether an activity object is recorded and sampled.</param>
 public SamplingResult(SamplingDecision decision)
 {
     this.Decision   = decision;
     this.Attributes = Enumerable.Empty <KeyValuePair <string, object> >();
 }