File: Telemetry\AspireTelemetryBaseTests.cs
Web Access
Project: src\tests\Aspire.Dashboard.Tests\Aspire.Dashboard.Tests.csproj (Aspire.Dashboard.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 Xunit;
 
namespace Aspire.Dashboard.Tests.Telemetry;
 
public class AspireTelemetryBaseTests
{
    [Theory]
    [InlineData(true)]
    [InlineData(false)]
    public void SetActivityProperties_AppliesPolicyWithoutAddingDefaultMetadata(bool batch)
    {
        using var fixture = new DashboardTelemetryFixture();
        using var telemetry = new TestTelemetryService(fixture);
        using var activity = telemetry.StartReportedActivity("test-operation");
        Assert.NotNull(activity);
        telemetry.SetActivityProperty(activity, "allowed.property", "original");
        KeyValuePair<string, object?>[] properties =
        [
            new("allowed.property", "updated"),
            new("secret.property", "private property")
        ];
 
        if (batch)
        {
            telemetry.SetActivityProperties(activity, properties);
        }
        else
        {
            foreach (var (key, value) in properties)
            {
                telemetry.SetActivityProperty(activity, key, value);
            }
        }
 
        Assert.Collection(activity.TagObjects,
            tag => Assert.Equal(new KeyValuePair<string, object?>("allowed.property", "UPDATED"), tag));
        Assert.Empty(activity.Events);
        Assert.False(fixture.LogChannel.Reader.TryPeek(out _));
    }
 
    [Fact]
    public void SetActivityProperties_WithNullActivity_DoesNotEnumerateProperties()
    {
        using var fixture = new DashboardTelemetryFixture();
        using var telemetry = new TestTelemetryService(fixture);
        var enumeratedCount = 0;
        var properties = Enumerable.Range(0, 1).Select(_ =>
        {
            enumeratedCount++;
            return new KeyValuePair<string, object?>("allowed.property", "value");
        });
 
        telemetry.SetActivityProperties(null, properties);
        telemetry.SetActivityProperty(null, "allowed.property", "value");
 
        Assert.Equal(0, enumeratedCount);
        Assert.False(fixture.ActivityChannel.Reader.TryPeek(out _));
        Assert.False(fixture.LogChannel.Reader.TryPeek(out _));
    }
 
    [Fact]
    public void Recording_AppliesPolicyToDefaultsAndPropertiesForActivitiesAndLogs()
    {
        using var fixture = new DashboardTelemetryFixture();
        using var telemetry = new TestTelemetryService(fixture);
        KeyValuePair<string, object?>[] properties =
        [
            new("allowed.property", "value"),
            new("secret.property", "private property")
        ];
        using var activity = telemetry.StartOperation(properties);
        Assert.NotNull(activity);
 
        telemetry.RecordEvent(properties);
 
        Assert.Collection(activity.TagObjects.OrderBy(t => t.Key, StringComparer.Ordinal),
            tag => Assert.Equal(new KeyValuePair<string, object?>("allowed.default", "DEFAULT"), tag),
            tag => Assert.Equal(new KeyValuePair<string, object?>("allowed.property", "VALUE"), tag));
        Assert.Empty(activity.Events);
        Assert.True(fixture.LogChannel.Reader.TryRead(out var log));
        Assert.Collection(log.Attributes,
            tag => Assert.Equal(new KeyValuePair<string, object?>("allowed.default", "DEFAULT"), tag),
            tag => Assert.Equal(new KeyValuePair<string, object?>("allowed.property", "VALUE"), tag),
            tag => Assert.Equal(new KeyValuePair<string, object?>("{OriginalFormat}", "test-event"), tag),
            tag => Assert.Equal(new KeyValuePair<string, object?>("microsoft.operation_name", "test-event"), tag));
        Assert.False(fixture.LogChannel.Reader.TryPeek(out _));
    }
 
    [Theory]
    [InlineData(true)]
    [InlineData(false)]
    public void RecordError_AppliesPolicyToDefaultsAndExceptionPropertiesWithoutCreatingActivity(bool withActivity)
    {
        using var fixture = new DashboardTelemetryFixture();
        using var telemetry = new TestTelemetryService(fixture);
        using var operation = withActivity ? telemetry.StartOperation([]) : null;
        var current = Activity.Current;
        var exception = new InvalidOperationException("private exception message");
 
        telemetry.RecordError("Local error", exception);
 
        Assert.Same(current, Activity.Current);
        Assert.False(fixture.ActivityChannel.Reader.TryPeek(out _));
        if (withActivity)
        {
            Assert.NotNull(operation);
            Assert.Collection(operation.TagObjects,
                tag => Assert.Equal(new KeyValuePair<string, object?>("allowed.default", "DEFAULT"), tag));
            Assert.Equal(ActivityStatusCode.Unset, operation.Status);
            Assert.Empty(operation.Events);
        }
 
        Assert.True(fixture.LogChannel.Reader.TryRead(out var log));
        Assert.Equal(current?.TraceId ?? default, log.TraceId);
        Assert.Equal(current?.SpanId ?? default, log.SpanId);
        Assert.Collection(log.Attributes,
            tag => Assert.Equal(new KeyValuePair<string, object?>("allowed.default", "DEFAULT"), tag),
            tag => Assert.Equal(new KeyValuePair<string, object?>("exception.type", typeof(InvalidOperationException).FullName!.ToUpperInvariant()), tag),
            tag => Assert.Equal(new KeyValuePair<string, object?>("{OriginalFormat}", "test-error"), tag),
            tag => Assert.Equal(new KeyValuePair<string, object?>("microsoft.operation_name", "test-error"), tag));
        Assert.False(fixture.LogChannel.Reader.TryPeek(out _));
    }
}