Aspect Generator (по мотивам "Новости C#12")
От: IT Россия linq2db.com
Дата: 22.11.23 03:05
Оценка: 177 (8)
В данном
Автор: Serginio1
Дата: 13.04.23
топике народ обсуждает новую экспериментальную фичу C# — Interceptors. При этом некоторые коллеги выразили сомнения, что это фича рабочая в частности для AOP.

В качестве подтверждения того, что это не так предлагаю взглянуть на проект, где это уже в определённой степени реализовано и некоторым образом работает.

По сути это реинкарнация аспектов из BLToolkit, кроме реализации самих аспектов. Сами аспекты предлагается реализовывать пользователям, т.к. с этим генератором это делается максимально просто (хотелось бы в это верить).

Пример для OpenTelemetry:

using System;
using System.Diagnostics;

using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;

namespace Aspects
{
    /// <summary>
    /// Initializes OpenTelemetry.
    /// </summary>
    static class OpenTelemetryFactory
    {
        public static TracerProvider? Create()
        {
            return Sdk.CreateTracerProviderBuilder()
                .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("MySample"))
                .AddSource("Sample.Aspect")
                .AddConsoleExporter()
                .Build();
        }
    }

    /// <summary>
    /// Metrics aspect.
    /// </summary>
    [Aspect(
        OnUsing   = nameof(OnUsing),
        OnFinally = nameof(OnFinally)
        )]
    [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
    sealed class MetricsAttribute : Attribute
    {
        static readonly ActivitySource _activitySource = new("Sample.Aspect");

        public static Activity? OnUsing(InterceptCallInfo info)
        {
            var activity = _activitySource.StartActivity(info.MemberInfo.Name);

            info.Tag = activity;

            return activity;
        }

        public static void OnFinally(InterceptCallInfo info)
        {
            if (info is { Tag: Activity activity, Exception: var ex })
                activity.SetStatus(ex is null ? ActivityStatusCode.Ok : ActivityStatusCode.Error);
        }
    }
}


Пример использования:

using System;
using System.Threading;

using Aspects;

namespace OpenTelemetryAspect
{
    static class Program
    {
        static void Main()
        {
            using var _ = OpenTelemetryFactory.Create();

            Method1();
            Method2();
            Method1();

            try
            {
                ExceptionMethod();
            }
            catch
            {
                // ignored
            }
        }

        [Metrics]
        public static void Method1()
        {
            Thread.Sleep(100);
        }

        [Metrics]
        public static void Method2()
        {
            Thread.Sleep(200);
        }

        [Metrics]
        public static void ExceptionMethod()
        {
            throw new();
        }
    }
}


Output:

Activity.TraceId:            f8d26974ff2dcbaeaab3be1d9c6aab97
Activity.SpanId:             e73ae5d740b585a2
Activity.TraceFlags:         Recorded
Activity.ActivitySourceName: Sample.Aspect
Activity.DisplayName:        Method1
Activity.Kind:               Internal
Activity.StartTime:          2023-11-22T03:09:22.4131051Z
Activity.Duration:           00:00:00.1116447
StatusCode: Ok
Resource associated with Activity:
    service.name: MySample
    service.instance.id: cef804b5-c54f-4b39-87af-0c78ac5123e3
    telemetry.sdk.name: opentelemetry
    telemetry.sdk.language: dotnet
    telemetry.sdk.version: 1.6.0

Activity.TraceId:            404b3b980f9ed8e9fddc850ffe648bcf
Activity.SpanId:             870afeb69f5bb3ca
Activity.TraceFlags:         Recorded
Activity.ActivitySourceName: Sample.Aspect
Activity.DisplayName:        Method2
Activity.Kind:               Internal
Activity.StartTime:          2023-11-22T03:09:22.5502315Z
Activity.Duration:           00:00:00.2070397
StatusCode: Ok
Resource associated with Activity:
    service.name: MySample
    service.instance.id: cef804b5-c54f-4b39-87af-0c78ac5123e3
    telemetry.sdk.name: opentelemetry
    telemetry.sdk.language: dotnet
    telemetry.sdk.version: 1.6.0

Activity.TraceId:            a0f781200e700fd686bbf48e914cf85a
Activity.SpanId:             86604cabc0961285
Activity.TraceFlags:         Recorded
Activity.ActivitySourceName: Sample.Aspect
Activity.DisplayName:        Method1
Activity.Kind:               Internal
Activity.StartTime:          2023-11-22T03:09:22.7672069Z
Activity.Duration:           00:00:00.1139825
StatusCode: Ok
Resource associated with Activity:
    service.name: MySample
    service.instance.id: cef804b5-c54f-4b39-87af-0c78ac5123e3
    telemetry.sdk.name: opentelemetry
    telemetry.sdk.language: dotnet
    telemetry.sdk.version: 1.6.0

Activity.TraceId:            6b9cae7c659e957c6ca834bb2a4ed135
Activity.SpanId:             86ce8c6a87fbe9f5
Activity.TraceFlags:         Recorded
Activity.ActivitySourceName: Sample.Aspect
Activity.DisplayName:        ExceptionMethod
Activity.Kind:               Internal
Activity.StartTime:          2023-11-22T03:09:22.8815192Z
Activity.Duration:           00:00:00.0001286
StatusCode: Error
Resource associated with Activity:
    service.name: MySample
    service.instance.id: cef804b5-c54f-4b39-87af-0c78ac5123e3
    telemetry.sdk.name: opentelemetry
    telemetry.sdk.language: dotnet
    telemetry.sdk.version: 1.6.0
Если нам не помогут, то мы тоже никого не пощадим.
Отредактировано 22.11.2023 3:10 IT . Предыдущая версия . Еще …
Отредактировано 22.11.2023 3:07 IT . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.