ASP.NET Core 中间件开发:请求日志记录与异常统一处理

ASP.NET Core 中间件开发:请求日志记录与异常统一处理

在 ASP.NET Core 中,中间件是处理 HTTP 请求和响应的核心组件。以下实现一个同时处理请求日志记录和全局异常捕获的中间件:

1. 创建中间件类
public class GlobalExceptionMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<GlobalExceptionMiddleware> _logger;

    public GlobalExceptionMiddleware(
        RequestDelegate next, 
        ILogger<GlobalExceptionMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var watch = Stopwatch.StartNew();
        try
        {
            // 调用管道中的下一个中间件
            await _next(context);
        }
        catch (Exception ex)
        {
            // 异常处理
            await HandleExceptionAsync(context, ex);
        }
        finally
        {
            // 记录请求日志
            watch.Stop();
            LogRequest(context, watch.ElapsedMilliseconds);
        }
    }

    private async Task HandleExceptionAsync(HttpContext context, Exception ex)
    {
        _logger.LogError(ex, "全局异常: {Message}", ex.Message);
        
        context.Response.StatusCode = StatusCodes.Status500InternalServerError;
        context.Response.ContentType = "application/json";
        
        await context.Response.WriteAsync(JsonSerializer.Serialize(new
        {
            Code = 500,
            Message = "服务器内部错误",
            Detail = ex.Message
        }));
    }

    private void LogRequest(HttpContext context, long elapsedMs)
    {
        _logger.LogInformation(
            "请求: {Method} {Path} | 响应: {StatusCode} | 耗时: {Elapsed}ms",
            context.Request.Method,
            context.Request.Path,
            context.Response.StatusCode,
            elapsedMs);
    }
}

2. 注册中间件(Program.cs)
// 必须放在管道最前端以捕获所有异常
app.UseMiddleware<GlobalExceptionMiddleware>();

// 其他中间件注册
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

3. 关键设计说明
  1. 日志记录功能

    • 使用 Stopwatch 精确计算请求处理时间
    • 记录请求方法、路径、响应状态码和耗时
    • 日志级别:Information(正常请求)/Error(异常请求)
  2. 异常统一处理

    • 捕获所有未处理异常
    • 返回标准化 JSON 错误响应:
      {
        "Code": 500,
        "Message": "服务器内部错误",
        "Detail": "具体错误信息"
      }
      

    • 自动记录异常堆栈(LogError)
  3. 性能优化点

    • 使用异步方法避免阻塞
    • 异常处理中复用 HTTP 上下文对象
    • 内置依赖注入支持(通过构造函数注入 ILogger)
4. 扩展建议
  1. 自定义异常处理
// 在 HandleExceptionAsync 中添加
switch (ex)
{
    case UnauthorizedAccessException:
        context.Response.StatusCode = 401;
        break;
    case ValidationException:
        context.Response.StatusCode = 400;
        break;
}

  1. 敏感信息过滤
// 生产环境隐藏异常详情
if (!app.Environment.IsDevelopment())
{
    await context.Response.WriteAsync(JsonSerializer.Serialize(new
    {
        Code = 500,
        Message = "服务器内部错误"
    }));
}

5. 工作流程
graph TD
    A[请求进入] --> B[开始计时]
    B --> C{执行后续中间件}
    C -->|成功| D[记录请求日志]
    C -->|异常| E[记录异常并生成响应]
    E --> D
    D --> F[返回响应]

此实现满足以下要求:

  • 统一处理所有未捕获异常
  • 自动记录请求关键指标
  • 返回标准化错误格式
  • 支持灵活的日志配置
  • 确保异常不会导致服务崩溃

注意:中间件注册顺序至关重要,必须置于管道最前端才能捕获后续中间件的所有异常。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值