public void ValidateStatusForAzureMonitorTrace(string activityStatusCode, string activityStatusDescription) { using ActivitySource activitySource = new ActivitySource(ActivitySourceName); using var activity = activitySource.StartActivity( ActivityName, ActivityKind.Server, parentContext: new ActivityContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.Recorded), startTime: DateTime.UtcNow); activity.SetTag("otel.status_code", activityStatusCode); activity.SetTag("otel.status_description", activityStatusDescription); activity.SetTag(SemanticConventions.AttributeHttpUrl, "https://www.foo.bar/search"); var monitorTags = TraceHelper.EnumerateActivityTags(activity); var requestData = new RequestData(2, activity, ref monitorTags); var remoteDependencyData = new RemoteDependencyData(2, activity, ref monitorTags); Assert.Equal(activity.GetStatus().StatusCode != StatusCode.Error, requestData.Success); Assert.Equal(activity.GetStatus().StatusCode != StatusCode.Error, remoteDependencyData.Success); }
// Applies the given sampler to NUM_SAMPLE_TRIES random traceId/spanId pairs. private static void AssertSamplerSamplesWithProbability( ISampler sampler, SpanContext parent, List <Link> links, double probability) { var count = 0; // Count of spans with sampling enabled for (var i = 0; i < NUM_SAMPLE_TRIES; i++) { if (sampler.ShouldSample( parent, ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), SPAN_NAME, links).IsSampled) { count++; } } var proportionSampled = (double)count / NUM_SAMPLE_TRIES; // Allow for a large amount of slop (+/- 10%) in number of sampled traces, to avoid flakiness. Assert.True(proportionSampled <probability + 0.1 && proportionSampled> probability - 0.1); }
public async Task SuccessfulTemplateControllerCallUsesParentContext() { var spanProcessor = new Mock <ActivityProcessor>(); var expectedTraceId = ActivityTraceId.CreateRandom(); var expectedSpanId = ActivitySpanId.CreateRandom(); // Arrange using (var testFactory = this.factory .WithWebHostBuilder(builder => builder.ConfigureTestServices(services => { this.openTelemetrySdk = OpenTelemetrySdk.EnableOpenTelemetry((builder) => builder.AddRequestInstrumentation() .AddProcessorPipeline(p => p.AddProcessor(n => spanProcessor.Object))); }))) { using var client = testFactory.CreateClient(); var request = new HttpRequestMessage(HttpMethod.Get, "/api/values/2"); request.Headers.Add("traceparent", $"00-{expectedTraceId}-{expectedSpanId}-01"); // Act var response = await client.SendAsync(request); // Assert response.EnsureSuccessStatusCode(); // Status Code 200-299 WaitForProcessorInvocations(spanProcessor, 2); } Assert.Equal(2, spanProcessor.Invocations.Count); // begin and end was called var span = (Activity)spanProcessor.Invocations[1].Arguments[0]; Assert.Equal(ActivityKind.Server, span.Kind); Assert.Equal("api/Values/{id}", span.DisplayName); Assert.Equal("/api/values/2", span.Tags.FirstOrDefault(i => i.Key == SpanAttributeConstants.HttpPathKey).Value); Assert.Equal(expectedTraceId, span.Context.TraceId); Assert.Equal(expectedSpanId, span.ParentSpanId); }
public void DroppingLinksEnumerable() { var contextLink = new SpanContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None); var maxNumberOfLinks = 8; var traceConfig = new TracerConfiguration(Samplers.AlwaysSample, 32, 128, maxNumberOfLinks); var tracer = TracerFactory.Create(b => b .AddProcessorPipeline(p => p.AddProcessor(n => spanProcessor)) .SetTracerOptions(traceConfig)) .GetTracer(null); var overflowedLinks = new List <Link>(); var link = new Link(contextLink); for (var i = 0; i < 2 * maxNumberOfLinks; i++) { overflowedLinks.Add(link); } var span = (Span)tracer.StartSpan(SpanName, SpanKind.Client, new SpanCreationOptions { Links = overflowedLinks, }); Assert.Equal(maxNumberOfLinks, span.Links.Count()); foreach (var actualLink in span.Links) { Assert.Equal(link, actualLink); } span.End(); Assert.Equal(maxNumberOfLinks, span.Links.Count()); foreach (var actualLink in span.Links) { Assert.Equal(link, actualLink); } }
public void StartRemoteSpan() { var spanContext = SpanContext.Create( ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Builder.Set("k1", "v1").Build()); var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTraceConfig) .SetSpanKind(SpanKind.Internal) .SetParent(spanContext) .SetRecordEvents(true) .StartSpan(); Assert.True(span.Context.IsValid); Assert.Equal(spanContext.TraceId, span.Context.TraceId); Assert.True((span.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); Assert.Equal(spanContext.SpanId, span.ParentSpanId); Assert.Equal("k1=v1", span.Context.Tracestate.ToString()); }
public void GeneratePartAEnvelope_Activity_WithParentSpanId() { using ActivitySource activitySource = new ActivitySource(ActivitySourceName); using var activity = activitySource.StartActivity( ActivityName, ActivityKind.Client, parentContext: new ActivityContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.Recorded), startTime: DateTime.UtcNow); var resource = CreateTestResource(); var monitorTags = AzureMonitorConverter.EnumerateActivityTags(activity); var telemetryItem = TelemetryPartA.GetTelemetryItem(activity, ref monitorTags, resource, null); Assert.Equal("RemoteDependency", telemetryItem.Name); Assert.Equal(TelemetryPartA.FormatUtcTimestamp(activity.StartTimeUtc), telemetryItem.Time); Assert.StartsWith("unknown_service", telemetryItem.Tags[ContextTagKeys.AiCloudRole.ToString()]); Assert.Equal(Dns.GetHostName(), telemetryItem.Tags[ContextTagKeys.AiCloudRoleInstance.ToString()]); Assert.NotNull(telemetryItem.Tags[ContextTagKeys.AiOperationId.ToString()]); Assert.NotNull(telemetryItem.Tags[ContextTagKeys.AiInternalSdkVersion.ToString()]); Assert.Equal(activity.ParentSpanId.ToHexString(), telemetryItem.Tags[ContextTagKeys.AiOperationParentId.ToString()]); }
public LinkTest() { this.spanContext = new SpanContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None); this.attributesMap.Add("MyAttributeKey0", "MyStringAttribute"); this.attributesMap.Add("MyAttributeKey1", 10L); this.attributesMap.Add("MyAttributeKey2", true); this.attributesMap.Add("MyAttributeKey3", 0.005); this.attributesMap.Add("MyAttributeKey4", new long[] { 1, 2 }); this.attributesMap.Add("MyAttributeKey5", new string[] { "a", "b" }); this.attributesMap.Add("MyAttributeKey6", new bool[] { true, false }); this.attributesMap.Add("MyAttributeKey7", new double[] { 0.1, -0.1 }); this.tags = new SpanAttributes(); this.tags.Add("MyAttributeKey0", "MyStringAttribute"); this.tags.Add("MyAttributeKey1", 10L); this.tags.Add("MyAttributeKey2", true); this.tags.Add("MyAttributeKey3", 0.005); this.tags.Add("MyAttributeKey4", new long[] { 1, 2 }); this.tags.Add("MyAttributeKey5", new string[] { "a", "b" }); this.tags.Add("MyAttributeKey6", new bool[] { true, false }); this.tags.Add("MyAttributeKey7", new double[] { 0.1, -0.1 }); }
public async Task TestTraceStateAndCorrelationContext() { try { using var eventRecords = new ActivitySourceRecorder(); var parent = new Activity("w3c activity"); parent.SetParentId(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom()); parent.TraceStateString = "some=state"; parent.AddBaggage("k", "v"); parent.Start(); // Send a random Http request to generate some events using (var client = new HttpClient()) { (await client.GetAsync(this.BuildRequestUrl())).Dispose(); } parent.Stop(); Assert.Equal(2, eventRecords.Records.Count()); // Check to make sure: The first record must be a request, the next record must be a response. (Activity activity, HttpWebRequest startRequest) = AssertFirstEventWasStart(eventRecords); var traceparent = startRequest.Headers["traceparent"]; var tracestate = startRequest.Headers["tracestate"]; var correlationContext = startRequest.Headers["Correlation-Context"]; Assert.NotNull(traceparent); Assert.Equal("some=state", tracestate); Assert.Equal("k=v", correlationContext); Assert.StartsWith($"00-{parent.TraceId.ToHexString()}-", traceparent); Assert.Matches("^[0-9a-f]{2}-[0-9a-f]{32}-[0-9a-f]{16}-[0-9a-f]{2}$", traceparent); } finally { this.CleanUpActivity(); } }
public void StartSpan_CurrentSpanParent() { var rootSpan = new SpanBuilder(SpanName, spanBuilderOptions) .SetParent( SpanContext.Create( ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Builder.Set("k1", "v1").Build())) .StartSpan(); using (tracer.WithSpan(rootSpan)) { var childSpan = (Span) new SpanBuilder(SpanName, spanBuilderOptions) .StartSpan(); Assert.True(childSpan.Context.IsValid); Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId); Assert.Equal(rootSpan.Context.SpanId, childSpan.ParentSpanId); Assert.Equal("k1=v1", childSpan.Context.Tracestate.ToString()); } }
public void TestW3CHeadersTraceStateAndCorrelationContext() { RemoteExecutor.Invoke(async() => { using (var eventRecords = new EventObserverAndRecorder()) { var parent = new Activity("w3c activity"); parent.SetParentId(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom()); parent.TraceStateString = "some=state"; parent.AddBaggage("k", "v"); parent.Start(); // Send a random Http request to generate some events using (var client = new HttpClient()) { (await client.GetAsync(Configuration.Http.RemoteEchoServer)).Dispose(); } parent.Stop(); // Check to make sure: The first record must be a request, the next record must be a response. Assert.True(eventRecords.Records.TryDequeue(out var evnt)); Assert.Equal("System.Net.Http.Desktop.HttpRequestOut.Start", evnt.Key); HttpWebRequest startRequest = ReadPublicProperty <HttpWebRequest>(evnt.Value, "Request"); Assert.NotNull(startRequest); var traceparent = startRequest.Headers["traceparent"]; var tracestate = startRequest.Headers["tracestate"]; var correlationContext = startRequest.Headers["Correlation-Context"]; Assert.NotNull(traceparent); Assert.Equal("some=state", tracestate); Assert.Equal("k=v", correlationContext); Assert.StartsWith($"00-{parent.TraceId.ToHexString()}-", traceparent); Assert.Matches("^[0-9a-f]{2}-[0-9a-f]{32}-[0-9a-f]{16}-[0-9a-f]{2}$", traceparent); Assert.Null(startRequest.Headers["Request-Id"]); } }).Dispose(); }
public void TelemetryPartBPropertiesContainsMSLinksWhenActivityHasLinks(string telemetryType) { using ActivitySource activitySource = new ActivitySource(ActivitySourceName); ActivityLink activityLink = new ActivityLink(new ActivityContext( ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None), null); List <ActivityLink> links = new List <ActivityLink>(); links.Add(activityLink); using var activity = activitySource.StartActivity( ActivityName, ActivityKind.Client, parentContext: default, null, links, startTime: DateTime.UtcNow); string expectedMSlinks = GetExpectedMSlinks(links); string actualMSlinks = null; var monitorTags = TraceHelper.EnumerateActivityTags(activity); if (telemetryType == "RequestData") { var telemetryPartBRequestData = new RequestData(2, activity, ref monitorTags); Assert.True(telemetryPartBRequestData.Properties.TryGetValue(msLinks, out actualMSlinks)); } if (telemetryType == "RemoteDependencyData") { var telemetryPartBRemoteDependencyData = new RemoteDependencyData(2, activity, ref monitorTags); Assert.True(telemetryPartBRemoteDependencyData.Properties.TryGetValue(msLinks, out actualMSlinks)); } Assert.Equal(expectedMSlinks, actualMSlinks); }
public void DoNotCrash() { IDictionary <string, object> attributes = new Dictionary <string, object>(); attributes.Add( "MyStringAttributeKey", "MyStringAttributeValue"); IDictionary <string, object> multipleAttributes = new Dictionary <string, object>(); multipleAttributes.Add( "MyStringAttributeKey", "MyStringAttributeValue"); multipleAttributes.Add("MyBooleanAttributeKey", true); multipleAttributes.Add("MyLongAttributeKey", 123); multipleAttributes.Add("MyDoubleAttributeKey", 0.005); // Tests only that all the methods are not crashing/throwing errors. BlankSpan.Instance.SetAttribute( "MyStringAttributeKey2", "MyStringAttributeValue2"); foreach (var a in attributes) { BlankSpan.Instance.SetAttribute(a); } foreach (var a in multipleAttributes) { BlankSpan.Instance.SetAttribute(a); } BlankSpan.Instance.AddEvent("MyEvent"); BlankSpan.Instance.AddEvent("MyEvent", attributes); BlankSpan.Instance.AddEvent("MyEvent", multipleAttributes); BlankSpan.Instance.AddEvent(new Event("MyEvent")); BlankSpan.Instance.AddLink(new Link(new SpanContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None))); Assert.False(BlankSpan.Instance.Context.IsValid); Assert.False(BlankSpan.Instance.IsRecordingEvents); Assert.Equal(Status.Ok, BlankSpan.Instance.Status); BlankSpan.Instance.Status = Status.Ok; BlankSpan.Instance.End(); }
public void StartSpan_WithLinkFromSpanContext() { var linkContext = SpanContext.Create( ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, Tracestate.Empty); var span = new SpanBuilder(SpanName, spanBuilderOptions) .SetSpanKind(SpanKind.Internal) .AddLink(linkContext) .StartSpan(); var spanData = ((Span)span).ToSpanData(); var links = spanData.Links.Links.ToArray(); Assert.Single(links); Assert.Equal(linkContext.TraceId, links[0].Context.TraceId); Assert.Equal(linkContext.SpanId, links[0].Context.SpanId); Assert.Equal(linkContext.TraceOptions, links[0].Context.TraceOptions); Assert.Equal(linkContext.Tracestate, links[0].Context.Tracestate); }
public void StartSpan_WithLink() { var link = new Link( new SpanContext( ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None)); var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTracerConfiguration, Resource.Empty) .SetSpanKind(SpanKind.Internal) .AddLink(link) .StartSpan(); var links = span.Links.ToArray(); Assert.Single(links); Assert.Equal(link.Context.TraceId, links[0].Context.TraceId); Assert.Equal(link.Context.SpanId, links[0].Context.SpanId); Assert.Equal(link.Context.TraceOptions, links[0].Context.TraceOptions); Assert.Equal(link.Context.Tracestate, links[0].Context.Tracestate); Assert.Equal(0, links[0].Attributes.Count); }
public void ProactivelySampledInItemsAreNotGivenPriorityIfRatesAreNotSet() { var sentTelemetry = new List <ITelemetry>(); TelemetryProcessorChain telemetryProcessorChainWithSampling = CreateTelemetryProcessorChainWithSampling( sentTelemetry, 50); for (int i = 0; i < 1000; i++) { var item = new RequestTelemetry(); item.Context.Operation.Id = ActivityTraceId.CreateRandom().ToHexString(); // proactively sample in items with big score, so they should not be sampled in if (SamplingScoreGenerator.GetSamplingScore(item.Context.Operation.Id) > 50) { item.ProactiveSamplingDecision = SamplingDecision.SampledIn; } telemetryProcessorChainWithSampling.Process(item); } Assert.AreEqual(0, sentTelemetry.Count(i => ((ISupportAdvancedSampling)i).ProactiveSamplingDecision == SamplingDecision.SampledIn)); }
public void ProcessorDoesNotBlockOnExporter() { spanExporter = new TestExporter(async _ => await Task.Delay(500)); tracer = TracerFactory.Create(b => b .SetExporter(spanExporter) .SetProcessor(e => new SimpleSpanProcessor(e))) .GetTracer(null); var context = new SpanContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.Recorded); var span = (Span)tracer.StartSpan("foo", context); // does not block var sw = Stopwatch.StartNew(); span.End(); sw.Stop(); Assert.InRange(sw.Elapsed, TimeSpan.Zero, TimeSpan.FromMilliseconds(100)); var exported = WaitForSpans(spanExporter, 1, TimeSpan.FromMilliseconds(600)); Assert.Single(exported); }
public async Task ProcessEvents_SingleDispatch_SystemPropertiesAndApplicationProperties() { var partitionContext = EventHubTests.GetPartitionContext(); var options = new EventHubOptions { BatchCheckpointFrequency = 1 }; var checkpointer = new Mock <EventHubListener.ICheckpointer>(); var loggerMock = new Mock <ILogger>(); var executor = new Mock <ITriggeredFunctionExecutor>(MockBehavior.Strict); executor.Setup(p => p.TryExecuteAsync(It.IsAny <TriggeredFunctionData>(), It.IsAny <CancellationToken>())).ReturnsAsync(new FunctionResult(true)); var eventProcessor = new EventHubListener.EventProcessor(options, executor.Object, loggerMock.Object, true, checkpointer.Object); var diagnosticId = $"00-{ActivityTraceId.CreateRandom().ToHexString()}-{ActivitySpanId.CreateRandom().ToHexString()}-01"; var eventData = new EventData(new byte[0]) { SystemProperties = new EventData.SystemPropertiesCollection(-1, DateTime.Now, "0", "1") { { "Diagnostic-Id", diagnosticId } }, // will be ignored Properties = { ["Diagnostic-Id"] = $"00-{ActivityTraceId.CreateRandom().ToHexString()}-{ActivitySpanId.CreateRandom().ToHexString()}-01" } }; await eventProcessor.ProcessEventsAsync(partitionContext, new[] { eventData }); Func <Dictionary <string, object>, bool> checkLinksScope = (scope) => scope.TryGetValue("Links", out var links) && links is IEnumerable <Activity> linksList && linksList.Count() == 1 && linksList.Single().ParentId == diagnosticId; loggerMock.Verify(l => l.BeginScope(It.Is <Dictionary <string, object> >(s => checkLinksScope(s))), Times.Once); }
internal static bool ShouldSample(SpanContext parentContext, string name, ISampler sampler, out SpanContext context, out ActivitySpanId parentSpanId) { ActivityTraceId traceId = default; var tracestate = Tracestate.Empty; parentSpanId = default; var parentOptions = ActivityTraceFlags.None; if (parentContext.IsValid) { traceId = parentContext.TraceId; parentSpanId = parentContext.SpanId; parentOptions = parentContext.TraceOptions; } else { traceId = ActivityTraceId.CreateRandom(); } var result = (parentOptions & ActivityTraceFlags.Recorded) != 0; var spanId = ActivitySpanId.CreateRandom(); var traceOptions = ActivityTraceFlags.None; if (sampler != null) { traceOptions = parentContext.TraceOptions; result = sampler.ShouldSample(parentContext, traceId, spanId, name, null); if (result) { traceOptions |= ActivityTraceFlags.Recorded; } } context = SpanContext.Create(traceId, spanId, traceOptions, parentContext.Tracestate); return(result); }
public void StartRemoteSpan() { var spanContext = new SpanContext( ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, new List <KeyValuePair <string, string> > { new KeyValuePair <string, string>("k1", "v1") }); var span = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTracerConfiguration, Resource.Empty) .SetSpanKind(SpanKind.Internal) .SetParent(spanContext) .SetRecordEvents(true) .StartSpan(); Assert.True(span.Context.IsValid); Assert.Equal(spanContext.TraceId, span.Context.TraceId); Assert.True((span.Context.TraceOptions & ActivityTraceFlags.Recorded) != 0); Assert.Equal(spanContext.SpanId, span.ParentSpanId); Assert.Equal("k1=v1", TracestateUtils.GetString(span.Context.Tracestate)); }
public void StartSpan_CurrentSpanParent() { var rootSpan = new SpanBuilder(SpanName, spanProcessor, alwaysSampleTracerConfiguration, Resource.Empty) .SetParent( new SpanContext( ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None, new List <KeyValuePair <string, string> > { new KeyValuePair <string, string>("k1", "v1") })) .StartSpan(); using (tracer.WithSpan(rootSpan)) { var childSpan = (Span) new SpanBuilder(SpanName, spanProcessor, alwaysSampleTracerConfiguration, Resource.Empty) .StartSpan(); Assert.True(childSpan.Context.IsValid); Assert.Equal(rootSpan.Context.TraceId, childSpan.Context.TraceId); Assert.Equal(rootSpan.Context.SpanId, childSpan.ParentSpanId); Assert.Equal("k1=v1", TracestateUtils.GetString(childSpan.Context.Tracestate)); } }
public void StartStopRespectsUserProvidedIdsInScopeOfAnotherActivityExplicitOperationIdOnly() { var activity = new Activity("foo").Start(); var customOperationId = ActivityTraceId.CreateRandom().ToHexString(); using (var operation = this.telemetryClient.StartOperation <DependencyTelemetry>("name", customOperationId)) { Assert.IsNotNull(Activity.Current); Assert.AreNotEqual(activity, Activity.Current.Parent); Assert.AreEqual(customOperationId, Activity.Current.TraceId.ToHexString()); Assert.AreEqual(customOperationId, operation.Telemetry.Context.Operation.Id); Assert.IsNull(operation.Telemetry.Context.Operation.ParentId); } Assert.AreEqual(activity, Activity.Current); Assert.AreEqual(1, this.sendItems.Count); Assert.IsTrue(this.sendItems.Single() is DependencyTelemetry); var dependency = this.sendItems.Single() as DependencyTelemetry; Assert.AreEqual(customOperationId, dependency.Context.Operation.Id); Assert.IsNull(dependency.Context.Operation.ParentId); }
private static async Task RunAsync() { var endpoint = "/delay/5ms"; using var listener = new HttpEventListener(); source = new ActivitySource("http-client-test"); var serviceCollection = new ServiceCollection(); serviceCollection.AddHttpOptionsTelemetry(builder => builder.AddConsoleExporter()); serviceCollection.AddHttpClientOptions(options => { options.ServiceName = "service"; options.Handler.MaxConnection = 500; _server.ConfigureWireMockServer(options); }); var services = serviceCollection.BuildServiceProvider(); await Task.WhenAll(services.GetServices <IHostedService>() .Select(e => e.StartAsync(CancellationToken.None))); var factory = services.GetRequiredService <IHttpClientFactory>(); var client = factory.CreateClient("service"); var stopwatch = Stopwatch.StartNew(); Console.WriteLine("oooo: "); do { try { await client.GetAsync(endpoint).ConfigureAwait(false); } catch (Exception e) { } } while (Console.ReadKey().Key != ConsoleKey.Escape); do { try { var activityLinks = new List <ActivityLink>(); var initialTags = new ActivityTagsCollection(); initialTags["com.mycompany.product.mytag1"] = "tagValue1"; initialTags["com.mycompany.product.mytag2"] = "tagValue2"; var linkedContext1 = new ActivityContext( ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None); var linkedContext2 = new ActivityContext( ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.Recorded); activityLinks.Add(new ActivityLink(linkedContext1)); activityLinks.Add(new ActivityLink(linkedContext2)); using var activity = source.StartActivity( "ActivityWithLinks", ActivityKind.Server, default(ActivityContext), initialTags, activityLinks); var latencyStats = await TrafficGenerator .GenerateTraffic(100, () => client.GetAsync(endpoint)) .Latency() .TakeUntil(DateTimeOffset.Now.AddSeconds(20)); Console.WriteLine(latencyStats.Print()); await client.GetAsync(endpoint).ConfigureAwait(false); System.Console.WriteLine("Press Enter key to continue."); } catch (Exception e) { Console.WriteLine(e); throw; } } while (Console.ReadKey().Key != ConsoleKey.Escape); }
public void ActivityTraceFlagsTests() { Activity activity; // Set the 'Recorded' bit by using SetParentId with a -01 flags. activity = new Activity("activity1"); activity.SetParentId("00-0123456789abcdef0123456789abcdef-0123456789abcdef-01"); activity.Start(); Assert.Equal(ActivityIdFormat.W3C, activity.IdFormat); Assert.Equal("0123456789abcdef0123456789abcdef", activity.TraceId.ToHexString()); Assert.Equal("0123456789abcdef", activity.ParentSpanId.ToHexString()); Assert.True(IdIsW3CFormat(activity.Id)); Assert.Equal($"00-0123456789abcdef0123456789abcdef-{activity.SpanId.ToHexString()}-01", activity.Id); Assert.Equal(ActivityTraceFlags.Recorded, activity.ActivityTraceFlags); Assert.True(activity.Recorded); activity.Stop(); // Set the 'Recorded' bit by using SetParentId by using the TraceId, SpanId, ActivityTraceFlags overload activity = new Activity("activity2"); ActivityTraceId activityTraceId = ActivityTraceId.CreateRandom(); activity.SetParentId(activityTraceId, ActivitySpanId.CreateRandom(), ActivityTraceFlags.Recorded); activity.Start(); Assert.Equal(ActivityIdFormat.W3C, activity.IdFormat); Assert.Equal(activityTraceId.ToHexString(), activity.TraceId.ToHexString()); Assert.True(IdIsW3CFormat(activity.Id)); Assert.Equal($"00-{activity.TraceId.ToHexString()}-{activity.SpanId.ToHexString()}-01", activity.Id); Assert.Equal(ActivityTraceFlags.Recorded, activity.ActivityTraceFlags); Assert.True(activity.Recorded); activity.Stop(); /****************************************************/ // Set the 'Recorded' bit explicitly after the fact. activity = new Activity("activity3"); activity.SetParentId("00-0123456789abcdef0123456789abcdef-0123456789abcdef-00"); activity.Start(); Assert.Equal(ActivityIdFormat.W3C, activity.IdFormat); Assert.Equal("0123456789abcdef0123456789abcdef", activity.TraceId.ToHexString()); Assert.Equal("0123456789abcdef", activity.ParentSpanId.ToHexString()); Assert.True(IdIsW3CFormat(activity.Id)); Assert.Equal($"00-{activity.TraceId.ToHexString()}-{activity.SpanId.ToHexString()}-00", activity.Id); Assert.Equal(ActivityTraceFlags.None, activity.ActivityTraceFlags); Assert.False(activity.Recorded); activity.ActivityTraceFlags = ActivityTraceFlags.Recorded; Assert.Equal(ActivityTraceFlags.Recorded, activity.ActivityTraceFlags); Assert.True(activity.Recorded); activity.Stop(); /****************************************************/ // Confirm that that flags are propagated to children. activity = new Activity("activity4"); activity.SetParentId("00-0123456789abcdef0123456789abcdef-0123456789abcdef-01"); activity.Start(); Assert.Equal(activity, Activity.Current); Assert.Equal(ActivityIdFormat.W3C, activity.IdFormat); Assert.Equal("0123456789abcdef0123456789abcdef", activity.TraceId.ToHexString()); Assert.Equal("0123456789abcdef", activity.ParentSpanId.ToHexString()); Assert.True(IdIsW3CFormat(activity.Id)); Assert.Equal($"00-{activity.TraceId.ToHexString()}-{activity.SpanId.ToHexString()}-01", activity.Id); Assert.Equal(ActivityTraceFlags.Recorded, activity.ActivityTraceFlags); Assert.True(activity.Recorded); // create a child var childActivity = new Activity("activity4Child"); childActivity.Start(); Assert.Equal(childActivity, Activity.Current); Assert.Equal("0123456789abcdef0123456789abcdef", childActivity.TraceId.ToHexString()); Assert.NotEqual(activity.SpanId.ToHexString(), childActivity.SpanId.ToHexString()); Assert.True(IdIsW3CFormat(childActivity.Id)); Assert.Equal($"00-{childActivity.TraceId.ToHexString()}-{childActivity.SpanId.ToHexString()}-01", childActivity.Id); Assert.Equal(ActivityTraceFlags.Recorded, childActivity.ActivityTraceFlags); Assert.True(childActivity.Recorded); childActivity.Stop(); activity.Stop(); }
public void IdFormatTests() { try { Activity activity; // Default format is the default (Hierarchical) activity = new Activity("activity1"); activity.Start(); Assert.Equal(ActivityIdFormat.Hierarchical, activity.IdFormat); activity.Stop(); // Set the parent to something that is W3C by string activity = new Activity("activity2"); activity.SetParentId("00-0123456789abcdef0123456789abcdef-0123456789abcdef-00"); activity.Start(); Assert.Equal(ActivityIdFormat.W3C, activity.IdFormat); Assert.Equal("0123456789abcdef0123456789abcdef", activity.TraceId.ToHexString()); Assert.Equal("0123456789abcdef", activity.ParentSpanId.ToHexString()); Assert.Equal(ActivityTraceFlags.None, activity.ActivityTraceFlags); Assert.False(activity.Recorded); Assert.True(IdIsW3CFormat(activity.Id)); activity.Stop(); // Set the parent to something that is W3C but using ActivityTraceId,ActivitySpanId version of SetParentId. activity = new Activity("activity3"); ActivityTraceId activityTraceId = ActivityTraceId.CreateRandom(); activity.SetParentId(activityTraceId, ActivitySpanId.CreateRandom()); activity.Start(); Assert.Equal(ActivityIdFormat.W3C, activity.IdFormat); Assert.Equal(activityTraceId.ToHexString(), activity.TraceId.ToHexString()); Assert.Equal(ActivityTraceFlags.None, activity.ActivityTraceFlags); Assert.False(activity.Recorded); Assert.True(IdIsW3CFormat(activity.Id)); activity.Stop(); // Change DefaultIdFormat to W3C, confirm I get the new format. Activity.DefaultIdFormat = ActivityIdFormat.W3C; activity = new Activity("activity4"); activity.Start(); Assert.Equal(ActivityIdFormat.W3C, activity.IdFormat); Assert.True(IdIsW3CFormat(activity.Id)); activity.Stop(); // But I don't get the default format if parent is hierarchical activity = new Activity("activity5"); string parentId = "|a000b421-5d183ab6.1"; activity.SetParentId(parentId); activity.Start(); Assert.Equal(ActivityIdFormat.Hierarchical, activity.IdFormat); Assert.True(activity.Id.StartsWith(parentId)); // Heirarchical Ids return null ActivityTraceId and ActivitySpanIds Assert.Equal("00000000000000000000000000000000", activity.TraceId.ToHexString()); Assert.Equal("0000000000000000", activity.SpanId.ToHexString()); activity.Stop(); // But if I set ForceDefaultFormat I get what I asked for (W3C format) Activity.ForceDefaultIdFormat = true; activity = new Activity("activity6"); activity.SetParentId(parentId); activity.Start(); Assert.Equal(ActivityIdFormat.W3C, activity.IdFormat); Assert.True(IdIsW3CFormat(activity.Id)); Assert.NotEqual("00000000000000000000000000000000", activity.TraceId.ToHexString()); Assert.NotEqual("0000000000000000", activity.SpanId.ToHexString()); /* TraceStateString testing */ // Test TraceStateString (that it inherits from parent) Activity parent = new Activity("parent"); string testString = "MyTestString"; parent.TraceStateString = testString; parent.Start(); Assert.Equal(testString, parent.TraceStateString); activity = new Activity("activity7"); activity.Start(); Assert.Equal(ActivityIdFormat.W3C, activity.IdFormat); Assert.True(IdIsW3CFormat(activity.Id)); Assert.Equal(testString, activity.TraceStateString); // Update child string childTestString = "ChildTestString"; activity.TraceStateString = childTestString; // Confirm that child sees update, but parent does not Assert.Equal(childTestString, activity.TraceStateString); Assert.Equal(testString, parent.TraceStateString); // Update parent string parentTestString = "newTestString"; parent.TraceStateString = parentTestString; // Confirm that parent sees update but child does not. Assert.Equal(childTestString, activity.TraceStateString); Assert.Equal(parentTestString, parent.TraceStateString); activity.Stop(); parent.Stop(); // Upper-case ids are not supported activity = new Activity("activity8"); activity.SetParentId("00-0123456789ABCDEF0123456789ABCDEF-0123456789ABCDEF-01"); activity.Start(); Assert.Equal(ActivityIdFormat.W3C, activity.IdFormat); Assert.True(IdIsW3CFormat(activity.Id)); activity.Stop(); // non hex chars are not supported in traceId activity = new Activity("activity9"); activity.SetParentId("00-xyz3456789abcdef0123456789abcdef-0123456789abcdef-01"); activity.Start(); Assert.Equal(ActivityIdFormat.W3C, activity.IdFormat); Assert.True(IdIsW3CFormat(activity.Id)); activity.Stop(); // non hex chars are not supported in parentSpanId activity = new Activity("activity10"); activity.SetParentId("00-0123456789abcdef0123456789abcdef-x123456789abcdef-01"); activity.Start(); Assert.Equal(ActivityIdFormat.W3C, activity.IdFormat); Assert.True(IdIsW3CFormat(activity.Id)); Assert.Equal("0000000000000000", activity.ParentSpanId.ToHexString()); Assert.Equal("0123456789abcdef0123456789abcdef", activity.TraceId.ToHexString()); activity.Stop(); // ParentSpanId from parent Activity Activity.DefaultIdFormat = ActivityIdFormat.W3C; Activity.ForceDefaultIdFormat = true; parent = new Activity("parent").Start(); activity = new Activity("parent").Start(); Assert.Equal(parent.SpanId.ToHexString(), activity.ParentSpanId.ToHexString()); activity.Stop(); parent.Stop(); } finally { // Set global settings back to the default, just to put the state back. Activity.ForceDefaultIdFormat = false; Activity.DefaultIdFormat = ActivityIdFormat.Hierarchical; Activity.Current = null; } }
public void ActivityTraceIdTests() { Span <byte> idBytes1 = stackalloc byte[16]; Span <byte> idBytes2 = stackalloc byte[16]; // Empty Constructor string zeros = "00000000000000000000000000000000"; ActivityTraceId emptyId = new ActivityTraceId(); Assert.Equal(zeros, emptyId.ToHexString()); emptyId.CopyTo(idBytes1); Assert.Equal(new byte[16], idBytes1.ToArray()); Assert.True(emptyId == new ActivityTraceId()); Assert.True(!(emptyId != new ActivityTraceId())); Assert.True(emptyId.Equals(new ActivityTraceId())); Assert.True(emptyId.Equals((object)new ActivityTraceId())); Assert.Equal(new ActivityTraceId().GetHashCode(), emptyId.GetHashCode()); // NewActivityTraceId ActivityTraceId newId1 = ActivityTraceId.CreateRandom(); Assert.True(IsLowerCaseHex(newId1.ToHexString())); Assert.Equal(32, newId1.ToHexString().Length); ActivityTraceId newId2 = ActivityTraceId.CreateRandom(); Assert.Equal(32, newId1.ToHexString().Length); Assert.NotEqual(newId1.ToHexString(), newId2.ToHexString()); // Test equality Assert.True(newId1 != newId2); Assert.True(!(newId1 == newId2)); Assert.True(!(newId1.Equals(newId2))); Assert.True(!(newId1.Equals((object)newId2))); Assert.NotEqual(newId1.GetHashCode(), newId2.GetHashCode()); ActivityTraceId newId3 = ActivityTraceId.CreateFromString("00000000000000000000000000000001".AsSpan()); Assert.True(newId3 != emptyId); Assert.True(!(newId3 == emptyId)); Assert.True(!(newId3.Equals(emptyId))); Assert.True(!(newId3.Equals((object)emptyId))); Assert.NotEqual(newId3.GetHashCode(), emptyId.GetHashCode()); // Use in Dictionary (this does assume we have no collisions in IDs over 100 tries (very good). var dict = new Dictionary <ActivityTraceId, string>(); for (int i = 0; i < 100; i++) { var newId7 = ActivityTraceId.CreateRandom(); dict[newId7] = newId7.ToHexString(); } int ctr = 0; foreach (string value in dict.Values) { string valueInDict; Assert.True(dict.TryGetValue(ActivityTraceId.CreateFromString(value.AsSpan()), out valueInDict)); Assert.Equal(value, valueInDict); ctr++; } Assert.Equal(100, ctr); // We got out what we put in. // AsBytes and Byte constructor. newId2.CopyTo(idBytes2); ActivityTraceId newId2Clone = ActivityTraceId.CreateFromBytes(idBytes2); Assert.Equal(newId2.ToHexString(), newId2Clone.ToHexString()); newId2Clone.CopyTo(idBytes1); Assert.Equal(idBytes2.ToArray(), idBytes1.ToArray()); Assert.True(newId2 == newId2Clone); Assert.True(newId2.Equals(newId2Clone)); Assert.True(newId2.Equals((object)newId2Clone)); Assert.Equal(newId2.GetHashCode(), newId2Clone.GetHashCode()); // String constructor and ToHexString(). string idStr = "0123456789abcdef0123456789abcdef"; ActivityTraceId id = ActivityTraceId.CreateFromString(idStr.AsSpan()); Assert.Equal(idStr, id.ToHexString()); // Utf8 Constructor. byte[] idUtf8 = Encoding.UTF8.GetBytes(idStr); ActivityTraceId id1 = ActivityTraceId.CreateFromUtf8String(idUtf8); Assert.Equal(idStr, id1.ToHexString()); // ToString Assert.Equal(idStr, id.ToString()); }
public void BuildSamplingParametersHandlesCurrentActivity() { using var activitySource = new ActivitySource(nameof(this.BuildSamplingParametersHandlesCurrentActivity)); var testSampler = new TestSampler { DesiredSamplingResult = new SamplingResult(true) }; using var listener = new ActivityListener { ShouldListenTo = _ => true, GetRequestedDataUsingContext = (ref ActivityCreationOptions <ActivityContext> options) => Sdk.ComputeActivityDataRequest(options, testSampler), }; ActivitySource.AddActivityListener(listener); using (var root = activitySource.StartActivity("root")) { Assert.Equal(default(ActivitySpanId), root.ParentSpanId); // This enforces the current behavior that the traceId passed to the sampler for the // root span/activity is not the traceId actually used. Assert.NotEqual(root.TraceId, testSampler.LatestSamplingParameters.TraceId); } using (var parent = activitySource.StartActivity("parent", ActivityKind.Client)) { // This enforces the current behavior that the traceId passed to the sampler for the // root span/activity is not the traceId actually used. Assert.NotEqual(parent.TraceId, testSampler.LatestSamplingParameters.TraceId); using (var child = activitySource.StartActivity("child")) { Assert.Equal(parent.TraceId, testSampler.LatestSamplingParameters.TraceId); Assert.Equal(parent.TraceId, child.TraceId); Assert.Equal(parent.SpanId, child.ParentSpanId); } } var customContext = new ActivityContext( ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None); using (var fromCustomContext = activitySource.StartActivity("customContext", ActivityKind.Client, customContext)) { Assert.Equal(customContext.TraceId, fromCustomContext.TraceId); Assert.Equal(customContext.SpanId, fromCustomContext.ParentSpanId); Assert.NotEqual(customContext.SpanId, fromCustomContext.SpanId); } // Preserve traceId in case span is propagated but not recorded (sampled per OpenTelemetry parlance) and // no data is requested for children spans. testSampler.DesiredSamplingResult = new SamplingResult(false); using (var root = activitySource.StartActivity("root")) { Assert.Equal(default(ActivitySpanId), root.ParentSpanId); using (var child = activitySource.StartActivity("child")) { Assert.Null(child); Assert.Equal(root.TraceId, testSampler.LatestSamplingParameters.TraceId); Assert.Same(Activity.Current, root); } } }
public void AllPropertiesShouldTranslate() { var startTs = DateTime.UtcNow; var endTs = startTs.AddSeconds(60); var evtTs = DateTime.UtcNow; var traceId = ActivityTraceId.CreateRandom(); var parentId = ActivitySpanId.CreateRandom(); var traceIdInt = traceId.ToLSTraceId(); var parentIdInt = parentId.ToLSSpanId(); var attrs = new Dictionary <string, object> { ["stringKey"] = "foo", ["longKey"] = 1L, ["doubleKey"] = 1D, ["boolKey"] = true, }; var evts = new List <Event> { new Event( "evt1", evtTs, new Dictionary <string, object> { { "key", "value" }, } ), new Event( "evt2", evtTs, new Dictionary <string, object> { { "key", "value" }, } ), }; var linkedSpanId = ActivitySpanId.CreateRandom(); var link = new Link(new Trace.SpanContext( traceId, linkedSpanId, ActivityTraceFlags.Recorded)); var span = (Span)tracer .StartSpan("Test", new Trace.SpanContext(traceId, parentId, ActivityTraceFlags.Recorded), SpanKind.Client, new SpanCreationOptions { StartTimestamp = startTs, Links = new[] { link }, }); var spanIdInt = span.Context.SpanId.ToLSSpanId(); foreach (var attribute in attrs) { span.SetAttribute(attribute.Key, attribute.Value); } foreach (var evnt in evts) { span.AddEvent(evnt); } span.End(endTs); span.Status = Status.Ok; var lsSpan = span.ToLightStepSpan(); Assert.Equal("Test", lsSpan.OperationName); Assert.Equal(2, lsSpan.Logs.Count); Assert.Equal(4, lsSpan.Tags.Count); Assert.Equal(traceIdInt, lsSpan.SpanContext.TraceId); Assert.Equal(spanIdInt, lsSpan.SpanContext.SpanId); Assert.Equal(parentIdInt, lsSpan.References[0].SpanContext.SpanId); }
public async Task EventHub_MultipleDispatch_IndependentMessages() { // send individual messages via EventHub client, process batch by host await using var ehClient = new EventHubProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, _eventHubScope.EventHubName); var messages = new EventData[5]; var expectedLinks = new TestLink[messages.Length]; for (int i = 0; i < messages.Length; i++) { var operationId = ActivityTraceId.CreateRandom().ToHexString(); var spanId = ActivitySpanId.CreateRandom().ToHexString(); expectedLinks[i] = new TestLink { operation_Id = operationId, id = spanId }; messages[i] = new EventData(Encoding.UTF8.GetBytes(i.ToString())) { Properties = { ["Diagnostic-Id"] = $"00-{operationId}-{spanId}-01" } }; } await ehClient.SendAsync(messages); var(jobHost, host) = BuildHost <EventHubTestMultipleDispatchJobs>(); using (host) { bool result = _eventWait.WaitOne(Timeout); Assert.True(result); } List <RequestTelemetry> requests = _channel.Telemetries.OfType <RequestTelemetry>().ToList(); var ehTriggerRequests = requests.Where(r => r.Context.Operation.Name == nameof(EventHubTestMultipleDispatchJobs.ProcessMultipleEvents)); List <TestLink> actualLinks = new List <TestLink>(); foreach (var ehTriggerRequest in ehTriggerRequests) { ValidateEventHubRequest( ehTriggerRequest, true, EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, _eventHubScope.EventHubName, nameof(EventHubTestMultipleDispatchJobs.ProcessMultipleEvents), null, null); Assert.NotNull(ehTriggerRequest.Context.Operation.Id); Assert.Null(ehTriggerRequest.Context.Operation.ParentId); Assert.True(ehTriggerRequest.Properties.TryGetValue("_MS.links", out var linksStr)); actualLinks.AddRange(JsonConvert.DeserializeObject <TestLink[]>(linksStr, jsonSettingThrowOnError)); } Assert.AreEqual(expectedLinks.Length, actualLinks.Count); foreach (var link in actualLinks) { Assert.True(expectedLinks.Any(l => l.operation_Id == link.operation_Id && l.id == link.id)); } }
public async Task CustomPropagator() { 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 => { Sdk.SetDefaultTextMapPropagator(propagator.Object); this.openTelemetrySdk = Sdk.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: ActivityCreatedByHttpInListener // 4. OnEnd for the sibling activity created by the instrumentation library with the OperationName: ActivityCreatedByHttpInListener 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.Contains(startedActivities, item => { var startedActivity = item.Arguments[0] as Activity; return(startedActivity.OperationName == HttpInListener.ActivityOperationName); }); Assert.Contains(startedActivities, item => { var startedActivity = item.Arguments[0] as Activity; return(startedActivity.OperationName == HttpInListener.ActivityNameByHttpInListener); }); // Only the sibling activity is sent to Processor.OnEnd Assert.Contains(stoppedActivities, item => { var stoppedActivity = item.Arguments[0] as Activity; return(stoppedActivity.OperationName == HttpInListener.ActivityNameByHttpInListener); }); var activity = activityProcessor.Invocations.FirstOrDefault(invo => invo.Method.Name == "OnEnd").Arguments[0] as Activity; Assert.Equal(ActivityKind.Server, activity.Kind); Assert.True(activity.Duration != TimeSpan.Zero); Assert.Equal("api/Values/{id}", activity.DisplayName); Assert.Equal("/api/values/2", activity.GetTagValue(SpanAttributeConstants.HttpPathKey) as string); Assert.Equal(expectedTraceId, activity.Context.TraceId); Assert.Equal(expectedSpanId, activity.ParentSpanId); Sdk.SetDefaultTextMapPropagator(new CompositeTextMapPropagator(new TextMapPropagator[] { new TraceContextPropagator(), new BaggagePropagator(), })); }
public static string GenerateTraceId() { return(ActivityTraceId.CreateRandom().ToHexString()); }