abd9d1b4a8
Task 8.1-8.3 - 错误处理和日志系统: - GlobalExceptionHandler: 全局异常处理中间件 - 统一错误响应格式 (ErrorResponse) - 自动分类处理各种异常类型 - 支持 Serilog 日志配置 (appsettings.json) - 请求日志中间件集成 - 详细的日志输出和错误追踪 Task 5.3-5.4 - CLI 高级功能: - CliConfiguration: CLI 配置文件管理 - stats 命令:显示转换统计信息 - config 命令:配置 CLI 参数 - 支持用户级别配置文件 (~/.codeplay/config.json) - 可配置的默认语言和验证轮次 - 并发控制选项 Task 6.1-6.2 - 报告展示完善: - ReportView.vue: 报告管理界面 - 统计卡片展示(总转换、项目、问题、平均行数) - 报告列表表格(支持排序和筛选) - 报告详情对话框 - 代码对比视图 - TODO 和问题列表展示 - 导出和删除功能 - 路由配置更新 测试:42 个 (41 通过,1 跳过) ✅ 新增文件: - CodePlay.WebAPI/Middleware/GlobalExceptionHandler.cs - CodePlay.WebAPI/appsettings.json (Serilog 配置) - CodePlay.CLI/Config/CliConfiguration.cs - CodePlay.Web/src/views/ReportView.vue Co-authored-by: monkeycode-ai <monkeycode-ai@chaitin.com>
125 lines
4.0 KiB
C#
125 lines
4.0 KiB
C#
using System.Net;
|
|
using System.Text.Json;
|
|
|
|
namespace CodePlay.WebAPI.Middleware;
|
|
|
|
/// <summary>
|
|
/// 全局异常处理中间件
|
|
/// </summary>
|
|
public class GlobalExceptionHandler
|
|
{
|
|
private readonly RequestDelegate _next;
|
|
private readonly ILogger<GlobalExceptionHandler> _logger;
|
|
|
|
public GlobalExceptionHandler(RequestDelegate next, ILogger<GlobalExceptionHandler> logger)
|
|
{
|
|
_next = next;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task InvokeAsync(HttpContext context)
|
|
{
|
|
try
|
|
{
|
|
await _next(context);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await HandleExceptionAsync(context, ex);
|
|
}
|
|
}
|
|
|
|
private async Task HandleExceptionAsync(HttpContext context, Exception exception)
|
|
{
|
|
var response = context.Response;
|
|
response.ContentType = "application/json";
|
|
|
|
var errorResponse = new ErrorResponse
|
|
{
|
|
RequestId = context.TraceIdentifier,
|
|
Timestamp = DateTime.UtcNow,
|
|
Path = context.Request.Path,
|
|
Method = context.Request.Method
|
|
};
|
|
|
|
switch (exception)
|
|
{
|
|
case UnauthorizedAccessException:
|
|
response.StatusCode = (int)HttpStatusCode.Unauthorized;
|
|
errorResponse.Code = "UNAUTHORIZED";
|
|
errorResponse.Message = "未授权访问";
|
|
_logger.LogWarning(exception, "未授权访问尝试");
|
|
break;
|
|
|
|
case ArgumentException argumentEx:
|
|
response.StatusCode = (int)HttpStatusCode.BadRequest;
|
|
errorResponse.Code = "BAD_REQUEST";
|
|
errorResponse.Message = argumentEx.Message;
|
|
_logger.LogWarning(exception, "参数验证失败");
|
|
break;
|
|
|
|
case KeyNotFoundException:
|
|
response.StatusCode = (int)HttpStatusCode.NotFound;
|
|
errorResponse.Code = "NOT_FOUND";
|
|
errorResponse.Message = "资源不存在";
|
|
_logger.LogWarning(exception, "资源未找到");
|
|
break;
|
|
|
|
case InvalidOperationException invalidEx:
|
|
response.StatusCode = (int)HttpStatusCode.Conflict;
|
|
errorResponse.Code = "CONFLICT";
|
|
errorResponse.Message = invalidEx.Message;
|
|
_logger.LogWarning(exception, "操作无效");
|
|
break;
|
|
|
|
case TimeoutException:
|
|
response.StatusCode = (int)HttpStatusCode.GatewayTimeout;
|
|
errorResponse.Code = "TIMEOUT";
|
|
errorResponse.Message = "请求超时";
|
|
_logger.LogError(exception, "请求超时");
|
|
break;
|
|
|
|
default:
|
|
response.StatusCode = (int)HttpStatusCode.InternalServerError;
|
|
errorResponse.Code = "INTERNAL_ERROR";
|
|
errorResponse.Message = "服务器内部错误";
|
|
_logger.LogError(exception, "未处理的异常");
|
|
break;
|
|
}
|
|
|
|
var options = new JsonSerializerOptions
|
|
{
|
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
|
WriteIndented = true
|
|
};
|
|
|
|
var jsonResponse = JsonSerializer.Serialize(errorResponse, options);
|
|
await response.WriteAsync(jsonResponse);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 错误响应模型
|
|
/// </summary>
|
|
public class ErrorResponse
|
|
{
|
|
public string RequestId { get; set; } = "";
|
|
public DateTime Timestamp { get; set; }
|
|
public string Code { get; set; } = "";
|
|
public string Message { get; set; } = "";
|
|
public string Path { get; set; } = "";
|
|
public string Method { get; set; } = "";
|
|
public Dictionary<string, string>? Details { get; set; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// 中间件扩展
|
|
/// </summary>
|
|
public static class GlobalExceptionHandlerExtensions
|
|
{
|
|
public static IApplicationBuilder UseGlobalExceptionHandler(this IApplicationBuilder app)
|
|
{
|
|
return app.UseMiddleware<GlobalExceptionHandler>();
|
|
}
|
|
}
|