| File: Telemetry\CliTagEnrichmentProcessorTests.cs | Web Access |
| Project: src\tests\Aspire.Cli.Tests\Aspire.Cli.Tests.csproj (Aspire.Cli.Tests) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; using Aspire.Cli.Telemetry; using Microsoft.AspNetCore.InternalTesting; using Microsoft.Extensions.Logging.Abstractions; namespace Aspire.Cli.Tests.Telemetry; public class CliTagEnrichmentProcessorTests { [Fact] public void OnEnd_AppliesResolvedTagsToActivity() { using var fixture = new TelemetryFixture(); var processor = new CliTagEnrichmentProcessor(fixture.TagsSource); using var source = new ActivitySource($"Test.{Path.GetRandomFileName()}"); using var listener = new ActivityListener { ShouldListenTo = s => s.Name == source.Name, Sample = (ref ActivityCreationOptions<ActivityContext> _) => ActivitySamplingResult.AllDataAndRecorded }; ActivitySource.AddActivityListener(listener); using var activity = source.StartActivity("test-op")!; Assert.NotNull(activity); // Tags should not be present before OnEnd Assert.DoesNotContain(activity.Tags, t => t.Key == "aspire.cli.version"); processor.OnEnd(activity); // After OnEnd, enrichment tags are applied Assert.Contains(activity.Tags, t => t.Key == "aspire.cli.version"); Assert.Contains(activity.Tags, t => t.Key == "machine.device_id"); } [Fact] public async Task OnEnd_WhenTagsNotYetResolved_BlocksUntilTagsAvailable() { // Verifies the processor handles the synchronous wait path when tags // haven't completed yet (the GetResolvedTags blocking path). var tagsSource = new TelemetryTagsSource(NullLogger<TelemetryTagsSource>.Instance); // Gate the tag calculation behind a TaskCompletionSource so it hasn't completed // when OnEnd is called — this forces the blocking wait path in GetResolvedTags. var gate = new TaskCompletionSource<bool>(); var expectedTags = new List<KeyValuePair<string, object?>> { new("aspire.cli.version", "1.0.0-test"), new("machine.device_id", "test-device-id") }; tagsSource.StartCalculation(async () => { await gate.Task; return expectedTags; }); var processor = new CliTagEnrichmentProcessor(tagsSource); using var source = new ActivitySource($"Test.{Path.GetRandomFileName()}"); using var listener = new ActivityListener { ShouldListenTo = s => s.Name == source.Name, Sample = (ref ActivityCreationOptions<ActivityContext> _) => ActivitySamplingResult.AllDataAndRecorded }; ActivitySource.AddActivityListener(listener); using var activity = source.StartActivity("test-op")!; // OnEnd will block waiting for the tags — run it on a background thread var onEndTask = Task.Run(() => processor.OnEnd(activity)); // Tags should NOT be present yet (calculation is gated) Assert.False(onEndTask.IsCompleted); // Release the gate so GetResolvedTags unblocks gate.SetResult(true); // OnEnd should complete now await onEndTask.DefaultTimeout(); // Tags were applied via the blocking wait path Assert.Contains(activity.Tags, t => t.Key == "aspire.cli.version" && (string?)t.Value == "1.0.0-test"); Assert.Contains(activity.Tags, t => t.Key == "machine.device_id" && (string?)t.Value == "test-device-id"); } }