First Commit

This commit is contained in:
Jorge Luis caudillo esparza
2026-05-09 16:36:57 -07:00
parent 96ad4c0d3e
commit d0c284d9c0
131 changed files with 4009 additions and 0 deletions

View File

@@ -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
}));
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -0,0 +1,6 @@
namespace ADS.Helpers.Middleware.ADSException;
public sealed class LoggingOptions
{
public string LogFolder { get; set; } = "logs";
}