mirror of
https://github.com/meysamhadeli/booking-microservices.git
synced 2026-04-12 11:32:10 +08:00
133 lines
4.0 KiB
C#
133 lines
4.0 KiB
C#
using System.Diagnostics;
|
|
using System.Diagnostics.Metrics;
|
|
using System.Reflection;
|
|
using Microsoft.Extensions.Options;
|
|
|
|
namespace BuildingBlocks.OpenTelemetryCollector.DiagnosticsProvider;
|
|
|
|
public class CustomeDiagnosticsProvider(IMeterFactory meterFactory, IOptions<ObservabilityOptions> options)
|
|
: IDiagnosticsProvider
|
|
{
|
|
private readonly Version? _version = Assembly.GetCallingAssembly().GetName().Version;
|
|
private ActivitySource? _activitySource;
|
|
private ActivityListener? _listener;
|
|
private Meter? _meter;
|
|
|
|
public string InstrumentationName { get; } = options.Value.InstrumentationName ?? throw new ArgumentException("InstrumentationName cannot be null or empty.");
|
|
|
|
// https://learn.microsoft.com/en-us/dotnet/core/diagnostics/distributed-tracing-instrumentation-walkthroughs
|
|
public ActivitySource ActivitySource
|
|
{
|
|
get
|
|
{
|
|
if (_activitySource != null)
|
|
return _activitySource;
|
|
|
|
_activitySource = new(InstrumentationName, _version?.ToString());
|
|
|
|
_listener = new ActivityListener
|
|
{
|
|
ShouldListenTo = x => true,
|
|
Sample = (ref ActivityCreationOptions<ActivityContext> _) => ActivitySamplingResult.AllDataAndRecorded,
|
|
};
|
|
ActivitySource.AddActivityListener(_listener);
|
|
|
|
return _activitySource;
|
|
}
|
|
}
|
|
|
|
// https://learn.microsoft.com/en-us/dotnet/core/diagnostics/metrics-instrumentation
|
|
public Meter Meter
|
|
{
|
|
get
|
|
{
|
|
if (_meter != null)
|
|
return _meter;
|
|
|
|
_meter = meterFactory.Create(InstrumentationName, _version?.ToString());
|
|
|
|
return _meter;
|
|
}
|
|
}
|
|
|
|
public async Task ExecuteActivityAsync(
|
|
CreateActivityInfo createActivityInfo,
|
|
Func<Activity?, CancellationToken, Task> action,
|
|
CancellationToken cancellationToken = default
|
|
)
|
|
{
|
|
if (!options.Value.TracingEnabled)
|
|
{
|
|
await action(null, cancellationToken);
|
|
|
|
return;
|
|
}
|
|
|
|
using var activity =
|
|
ActivitySource
|
|
.CreateActivity(
|
|
name: $"{InstrumentationName}.{createActivityInfo.Name}",
|
|
kind: createActivityInfo.ActivityKind,
|
|
parentContext: createActivityInfo.Parent ?? default,
|
|
idFormat: ActivityIdFormat.W3C,
|
|
tags: createActivityInfo.Tags
|
|
)
|
|
?.Start() ?? Activity.Current;
|
|
|
|
try
|
|
{
|
|
await action(activity!, cancellationToken);
|
|
activity?.SetOkStatus();
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
activity?.SetErrorStatus(ex);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public async Task<TResult?> ExecuteActivityAsync<TResult>(
|
|
CreateActivityInfo createActivityInfo,
|
|
Func<Activity?, CancellationToken, Task<TResult>> action,
|
|
CancellationToken cancellationToken = default
|
|
)
|
|
{
|
|
if (!options.Value.TracingEnabled)
|
|
{
|
|
return await action(null, cancellationToken);
|
|
}
|
|
|
|
using var activity =
|
|
ActivitySource
|
|
.CreateActivity(
|
|
name: $"{InstrumentationName}.{createActivityInfo.Name}",
|
|
kind: createActivityInfo.ActivityKind,
|
|
parentContext: createActivityInfo.Parent ?? default,
|
|
idFormat: ActivityIdFormat.W3C,
|
|
tags: createActivityInfo.Tags
|
|
)
|
|
?.Start() ?? Activity.Current;
|
|
|
|
try
|
|
{
|
|
var result = await action(activity!, cancellationToken);
|
|
|
|
activity?.SetOkStatus();
|
|
|
|
return result;
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
activity?.SetErrorStatus(ex);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_listener?.Dispose();
|
|
_meter?.Dispose();
|
|
_activitySource?.Dispose();
|
|
}
|
|
}
|