Last active
March 27, 2024 09:14
-
-
Save djordjedjukic/c5ada10ff68f389b095d3bbc67a06d65 to your computer and use it in GitHub Desktop.
LoggingMiddleware
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Linq; | |
using System.Threading; | |
using System.Threading.Tasks; | |
using MediatR; | |
using Microsoft.ApplicationInsights; | |
using Microsoft.ApplicationInsights.DataContracts; | |
using Microsoft.AspNetCore.Http; | |
using MoveBoard.Core.Extensions; | |
using MoveBoard.Core.Infrastructure.Exceptions; | |
using Newtonsoft.Json; | |
namespace MoveBoard.Core.Infrastructure.Mediatr | |
{ | |
internal class LoggingPipelineBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> | |
where TRequest : IRequest<TResponse> | |
{ | |
private readonly IHttpContextAccessor _ctx; | |
private readonly TelemetryClient _telemetry; | |
public LoggingPipelineBehavior(IHttpContextAccessor ctx, TelemetryClient telemetry) | |
{ | |
_ctx = ctx; | |
_telemetry = telemetry; | |
} | |
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, | |
RequestHandlerDelegate<TResponse> next) | |
{ | |
long start = 0; | |
long stop; | |
try | |
{ | |
start = Stopwatch.GetTimestamp(); | |
var result = await next(); | |
stop = Stopwatch.GetTimestamp(); | |
_telemetry.TrackTrace("MediatR", SeverityLevel.Information, | |
Serialize(request, result, GetElapsedMilliseconds(start, stop))); | |
return result; | |
} | |
catch (Exception e) | |
{ | |
stop = Stopwatch.GetTimestamp(); | |
HandleExceptionAsync(e, request, start, stop); | |
throw; | |
} | |
} | |
private void HandleExceptionAsync(Exception exception, TRequest request, long start, long stop) | |
{ | |
var e = exception is AggregateException aggregateException | |
? aggregateException.Flatten().InnerExceptions.FirstOrDefault() | |
: exception; | |
switch (e) | |
{ | |
case UnauthorizedAccessException uae: | |
_telemetry.TrackTrace("MediatR", Serialize(request, default, GetElapsedMilliseconds(start, stop))); | |
return; | |
case ValidatingException ve: | |
_telemetry.TrackTrace("MediatR", | |
Serialize(request, default, GetElapsedMilliseconds(start, stop), ve.Errors)); | |
return; | |
} | |
_telemetry.TrackException(e, Serialize(request, default, GetElapsedMilliseconds(start, stop))); | |
} | |
private Dictionary<string, string> Serialize(TRequest request, TResponse result, double elapsedMs, | |
IEnumerable<ValidatingException.Error> errors = default) | |
{ | |
var serializationSettings = | |
new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore }; | |
var properties = new Dictionary<string, string> | |
{ | |
{ "Elapsed", $"{elapsedMs:0.0000}" }, | |
{ "Type", request.GetType().FullName }, | |
{ "Request", JsonConvert.SerializeObject(request, serializationSettings) }, | |
{ "Response", JsonConvert.SerializeObject(result, serializationSettings) } | |
}; | |
if (errors.IsNullOrEmpty() == false) | |
{ | |
properties.Add("Errors", JsonConvert.SerializeObject(errors, serializationSettings)); | |
} | |
return properties; | |
} | |
private double GetElapsedMilliseconds(long start, long stop) | |
{ | |
return (stop - start) * 1000 / (double)Stopwatch.Frequency; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment