First Commit
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace ADS.Helpers.Middleware.ADSException;
|
||||
|
||||
using ADS.Helpers.Middleware.Http;
|
||||
|
||||
public sealed class AdsExceptionMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly IAdsErrorLogger _logger;
|
||||
|
||||
public AdsExceptionMiddleware(RequestDelegate next, IAdsErrorLogger logger)
|
||||
{
|
||||
_next = next;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task InvokeAsync(HttpContext context)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _next(context);
|
||||
}
|
||||
catch (System.UnauthorizedAccessException ex)
|
||||
{
|
||||
await Handle(context, HttpStatusCode.Unauthorized, ex, AdsErrorKind.Controlled);
|
||||
}
|
||||
catch (ArgumentException ex)
|
||||
{
|
||||
await Handle(context, HttpStatusCode.BadRequest, ex, AdsErrorKind.Controlled);
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
await Handle(context, HttpStatusCode.BadRequest, ex, AdsErrorKind.Controlled);
|
||||
}
|
||||
catch (Microsoft.Data.SqlClient.SqlException ex)
|
||||
{
|
||||
await Handle(context, HttpStatusCode.InternalServerError, ex, AdsErrorKind.Sql);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await Handle(context, HttpStatusCode.InternalServerError, ex, AdsErrorKind.Unhandled);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task Handle(HttpContext ctx, HttpStatusCode code, Exception ex, AdsErrorKind kind)
|
||||
{
|
||||
await _logger.LogAsync(new AdsErrorEvent
|
||||
{
|
||||
Kind = kind,
|
||||
Path = ctx.Request.Path.ToString(),
|
||||
Method = ctx.Request.Method,
|
||||
TraceId = ctx.TraceIdentifier,
|
||||
Message = ex.Message,
|
||||
Exception = ex.ToString()
|
||||
});
|
||||
|
||||
ctx.Response.StatusCode = (int)code;
|
||||
ctx.Response.ContentType = "application/json";
|
||||
|
||||
var payload = new ApiResponse<object>
|
||||
{
|
||||
StatusCode = (int)code,
|
||||
StatusCodeText = code.ToString(),
|
||||
ConsoleMessage = ex.Message,
|
||||
ScreenMessage = new UiMessage
|
||||
{
|
||||
MessageType = 2, // ejemplo: 1=info,2=error,3=warn
|
||||
Message = "Ocurrió un error al procesar la solicitud.",
|
||||
MessageCode = 0
|
||||
},
|
||||
Value = null
|
||||
};
|
||||
|
||||
await ctx.Response.WriteAsync(JsonSerializer.Serialize(payload, new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Text.Json;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace ADS.Helpers.Middleware.ADSException;
|
||||
|
||||
public sealed class FileAdsErrorLogger : IAdsErrorLogger
|
||||
{
|
||||
private readonly string _folder;
|
||||
|
||||
public FileAdsErrorLogger(IOptions<LoggingOptions> options)
|
||||
{
|
||||
_folder = options.Value.LogFolder ?? "logs";
|
||||
Directory.CreateDirectory(_folder);
|
||||
}
|
||||
|
||||
public Task LogAsync(AdsErrorEvent evt, CancellationToken ct = default)
|
||||
{
|
||||
var day = DateTime.UtcNow.ToString("yyyy-MM-dd");
|
||||
var path = Path.Combine(_folder, $"ads-errors-{day}.jsonl");
|
||||
|
||||
var line = JsonSerializer.Serialize(evt);
|
||||
return File.AppendAllTextAsync(path, line + Environment.NewLine, ct);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
namespace ADS.Helpers.Middleware.ADSException;
|
||||
|
||||
public enum AdsErrorKind
|
||||
{
|
||||
Sql = 1,
|
||||
Controlled = 2,
|
||||
Unhandled = 3
|
||||
}
|
||||
|
||||
public sealed class AdsErrorEvent
|
||||
{
|
||||
public AdsErrorKind Kind { get; init; }
|
||||
public string? Path { get; init; }
|
||||
public string? Method { get; init; }
|
||||
public string? TraceId { get; init; }
|
||||
public string? Message { get; init; }
|
||||
public string? Exception { get; init; }
|
||||
public DateTime Utc { get; init; } = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
public interface IAdsErrorLogger
|
||||
{
|
||||
Task LogAsync(AdsErrorEvent evt, CancellationToken ct = default);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace ADS.Helpers.Middleware.ADSException;
|
||||
|
||||
public sealed class LoggingOptions
|
||||
{
|
||||
public string LogFolder { get; set; } = "logs";
|
||||
}
|
||||
Reference in New Issue
Block a user