File: Model\SpanType.cs
Web Access
Project: src\src\Aspire.Dashboard\Aspire.Dashboard.csproj (Aspire.Dashboard)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using Aspire.Dashboard.Model.Otlp;
using Aspire.Dashboard.Otlp.Model;
using Aspire.Dashboard.Resources;
using Microsoft.Extensions.Localization;
 
namespace Aspire.Dashboard.Model;
 
public class SpanType
{
    public string Name { get; }
    public TelemetryFilter Filter { get; }
 
    private SpanType(string name, TelemetryFilter filter)
    {
        Name = name;
        Filter = filter;
    }
 
    // https://opentelemetry.io/docs/specs/semconv/http/http-spans/
    public static readonly SpanType Http = new SpanType(
        "http",
        new SpanHasAttributeTelemetryFilter(["http.request.method"]));
 
    // https://opentelemetry.io/docs/specs/semconv/database/database-spans/
    public static readonly SpanType Database = new SpanType(
        "database",
        new SpanHasAttributeTelemetryFilter(["db.system.name", "db.system"]));
 
    // https://opentelemetry.io/docs/specs/semconv/messaging/messaging-spans/
    public static readonly SpanType Messaging = new SpanType(
        "messaging",
        new SpanHasAttributeTelemetryFilter(["messaging.system"]));
 
    // https://opentelemetry.io/docs/specs/semconv/rpc/rpc-spans/
    public static readonly SpanType Rpc = new SpanType(
        "rpc",
        new SpanHasAttributeTelemetryFilter(["rpc.system"]));
 
    // https://opentelemetry.io/docs/specs/semconv/gen-ai/gen-ai-spans/
    public static readonly SpanType GenAI = new SpanType(
        "genai",
        new SpanHasAttributeTelemetryFilter(["gen_ai.system", "gen_ai.provider.name"]));
 
    public static readonly SpanType Other = new SpanType(
        "other",
        new SpanNoAttributeTelemetryFilter([
            "http.request.method",
            "db.system.name",
            "db.system",
            "messaging.system",
            "rpc.system",
            "gen_ai.system",
            "gen_ai.provider.name"
        ]));
 
    public static List<SelectViewModel<SpanType>> CreateKnownSpanTypes(IStringLocalizer<ControlsStrings> loc)
    {
        return new List<SelectViewModel<SpanType>>
        {
            new() { Id = null, Name = loc[nameof(ControlsStrings.LabelAll)] },
            new() { Id = Http, Name = loc[nameof(ControlsStrings.SpanTypeHttp)] },
            new() { Id = Database, Name = loc[nameof(ControlsStrings.SpanTypeDatabase)] },
            new() { Id = Messaging, Name = loc[nameof(ControlsStrings.SpanTypeMessaging)] },
            new() { Id = Rpc, Name = loc[nameof(ControlsStrings.SpanTypeRpc)] },
            new() { Id = GenAI, Name = loc[nameof(ControlsStrings.SpanTypeGenAI)] },
            new() { Id = Other, Name = loc[nameof(ControlsStrings.LabelOther)] },
        };
    }
}
 
public class SpanHasAttributeTelemetryFilter : TelemetryFilter
{
    private readonly string[] _attributeNames;
 
    public SpanHasAttributeTelemetryFilter(string[] attributeNames)
    {
        _attributeNames = attributeNames;
    }
 
    public override IEnumerable<OtlpLogEntry> Apply(IEnumerable<OtlpLogEntry> input)
    {
        throw new NotSupportedException();
    }
 
    public override bool Apply(OtlpSpan span)
    {
        foreach (var attributeName in _attributeNames)
        {
            if (!string.IsNullOrEmpty(span.Attributes.GetValue(attributeName)))
            {
                return true;
            }
        }
 
        return false;
    }
 
    public override bool Equals(TelemetryFilter? other)
    {
        return false;
    }
}
 
public class SpanNoAttributeTelemetryFilter : TelemetryFilter
{
    private readonly string[] _attributeNames;
 
    public SpanNoAttributeTelemetryFilter(string[] attributeNames)
    {
        _attributeNames = attributeNames;
    }
 
    public override IEnumerable<OtlpLogEntry> Apply(IEnumerable<OtlpLogEntry> input)
    {
        throw new NotSupportedException();
    }
 
    public override bool Apply(OtlpSpan span)
    {
        foreach (var attributeName in _attributeNames)
        {
            if (!string.IsNullOrEmpty(span.Attributes.GetValue(attributeName)))
            {
                return false;
            }
        }
 
        return true;
    }
 
    public override bool Equals(TelemetryFilter? other)
    {
        return false;
    }
}