Сообщение Aspect Generator (по мотивам "Новости C#12") от 22.11.2023 3:05
Изменено 22.11.2023 3:10 IT
Aspect Generator (по мотивам "Новости C#12")
В данном
В качестве подтверждения того, что это не так предлагаю взглянуть на проект, где это уже в определённой степени реализовано и некоторым образом работает.
По сути это реинкарнация аспектов из BLToolkit, кроме реализации самих аспектов. Сами аспекты предлагается реализовывать пользователям, т.к. с этим генератором это делается максимально просто (хотелось бы в это верить).
Пример для OpenTelemetry:
Пример использования:
Автор: Serginio1
Дата: 13.04.23
топике народ обсуждает новую экспериментальную фичу C# — Interceptors. При этом некоторые коллеги выразили сомнения, что это фича рабочая в частности для AOP.Дата: 13.04.23
В качестве подтверждения того, что это не так предлагаю взглянуть на проект, где это уже в определённой степени реализовано и некоторым образом работает.
По сути это реинкарнация аспектов из 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();
}
}
}
Aspect Generator (по мотивам "Новости C#12")
В данном
В качестве подтверждения того, что это не так предлагаю взглянуть на проект, где это уже в определённой степени реализовано и некоторым образом работает.
По сути это реинкарнация аспектов из BLToolkit, кроме реализации самих аспектов. Сами аспекты предлагается реализовывать пользователям, т.к. с этим генератором это делается максимально просто (хотелось бы в это верить).
Пример для OpenTelemetry:
Пример использования:
Output:
Автор: Serginio1
Дата: 13.04.23
топике народ обсуждает новую экспериментальную фичу C# — Interceptors. При этом некоторые коллеги выразили сомнения, что это фича рабочая в частности для AOP.Дата: 13.04.23
В качестве подтверждения того, что это не так предлагаю взглянуть на проект, где это уже в определённой степени реализовано и некоторым образом работает.
По сути это реинкарнация аспектов из 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