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 . Предыдущая версия .
Re: Aspect Generator (по мотивам "Новости C#12")
От: rosencrantz США  
Дата: 23.11.23 23:35
Оценка:
Здравствуйте, IT, Вы писали:

IT>В данном
Автор: Serginio1
Дата: 13.04.23
топике народ обсуждает новую экспериментальную фичу C# — Interceptors. При этом некоторые коллеги выразили сомнения, что это фича рабочая в частности для AOP.


Не понятно зачем это тащить в язык, если через IoC-контейнеры уже сто лет делается без проблем. Как в MetricsAttribute предлагается инжектить зависимости? В предложенном примере — глобальные переменные во всей красе.
Re[2]: Aspect Generator (по мотивам "Новости C#12")
От: IT Россия linq2db.com
Дата: 24.11.23 04:09
Оценка:
Здравствуйте, rosencrantz, Вы писали:

R>Не понятно зачем это тащить в язык, если через IoC-контейнеры уже сто лет делается без проблем. Как в MetricsAttribute предлагается инжектить зависимости? В предложенном примере — глобальные переменные во всей красе.


Это другое.
Если нам не помогут, то мы тоже никого не пощадим.
Re: Aspect Generator (по мотивам "Новости C#12")
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 24.11.23 07:15
Оценка:
Здравствуйте, IT, Вы писали:

Предлагаю еще добавить фичу обертки метода по комментарию.
Часто нужно создать отдельную сборку с большей информацией о параметрах и возвратах в определенных местах
и солнце б утром не вставало, когда бы не было меня
Re[2]: Aspect Generator (по мотивам "Новости C#12")
От: IT Россия linq2db.com
Дата: 24.11.23 07:27
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Предлагаю еще добавить фичу обертки метода по комментарию.

S>Часто нужно создать отдельную сборку с большей информацией о параметрах и возвратах в определенных местах

Не понял.
Если нам не помогут, то мы тоже никого не пощадим.
Re[3]: Aspect Generator (по мотивам "Новости C#12")
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 24.11.23 07:33
Оценка:
Здравствуйте, IT, Вы писали:

S>>Предлагаю еще добавить фичу обертки метода по комментарию.

S>>Часто нужно создать отдельную сборку с большей информацией о параметрах и возвратах в определенных местах

IT>Не понял.




// Помечаю метод каким то определенным комментарием
 Method1();


И вызов метода превращается

public static void Method1_Interceptor()
{
    // Aspects.MetricsAttribute
    //
    var __info__0 = new Aspects.InterceptCallInfo<Void>
    {
        MemberInfo      = Method1_Interceptor_MemberInfo,
        AspectType      = typeof(Aspects.MetricsAttribute),
        AspectArguments = Method1_Interceptor_AspectArguments_0,
    };

    using (Aspects.MetricsAttribute.OnUsing(__info__0))
    {
        try
        {
            OpenTelemetryAspect.Program.Method1();
        }
        catch (Exception __ex__)
        {
            __info__0.Exception = __ex__;
            throw;
        }
        finally
        {
            __info__0.InterceptType = Aspects.InterceptType.OnFinally;
            Aspects.MetricsAttribute.OnFinally(__info__0);
        }
    }
}


Причем другие вызовы этого метода меня не интересуют. Только в конкретном месте. Там может несколько методов, что бы получить более детальную информацию.
и солнце б утром не вставало, когда бы не было меня
Отредактировано 24.11.2023 17:30 IT . Предыдущая версия .
Re: Оффтоп про почту
От: Sharov Россия  
Дата: 24.11.23 15:08
Оценка:
Здравствуйте, IT.

Очень прошу прощения за оффтоп, но Вы можете кого-нибудь пнуть из ответственных лиц с целью починки почты?
Ну или хотя бы причины озвучить, почему не работает -- забанили где-то, сломалось что-то или надо проплатить
чего-то?

Заранее благодарю.
Кодом людям нужно помогать!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.