利用过滤器实现全局异常和全局日志功能

本文介绍了如何在ASP.NET Core中利用过滤器实现全局异常捕获和日志记录功能。通过创建`GlobalExceptionFilter`和`LogActionFilter`,分别处理未处理的异常并记录请求日志。同时,定义了一个`NoLogAttribute`用于标记不需要记录日志的方法。在项目配置中注册这两个过滤器,确保所有请求都能被正确处理并记录日志。
摘要由CSDN通过智能技术生成

源码点我

又到了疯狂星期五了

今天我们利用过滤器实现一个全局异常和一个全局日志的功能。

废话不说,直接上干货:
1、新建一个Filters文件夹,添加文件GlobalExceptionFilter.cs,添加如下代码:

namespace NET6.Api.Filters;

public class GlobalExceptionFilter : IExceptionFilter
{
    readonly IWebHostEnvironment hostEnvironment;
    public GlobalExceptionFilter(IWebHostEnvironment _hostEnvironment)
    {
        hostEnvironment = _hostEnvironment;
    }
    public void OnException(ExceptionContext context)
    {
        if (!context.ExceptionHandled)
        {
            var result = new JsonView
            {
                Code = (int)HttpStatusCode.InternalServerError,
                Msg = "服务器发生未处理的异常"
            };
            if (hostEnvironment.IsDevelopment())
            {
                result.Msg += ":" + context.Exception.Message;
                result.Data = context.Exception.StackTrace;
            }
            context.Result = new ContentResult
            {
                StatusCode = (int)HttpStatusCode.InternalServerError,
                ContentType = "application/json;charset=utf-8",
                Content = result.ToJson()
            };
            Log.Error($"服务器内部错误:{result.ToJson()}");
            context.ExceptionHandled = true;
        }
    }
}

2、同样新建LogActionFilter.cs,添加如下代码:

namespace NET6.Api.Filters;

/// <summary>
/// 日志过滤器
/// </summary>
public class LogActionFilter : IAsyncActionFilter
{
    readonly OperationLogRepository _logRep;
    public LogActionFilter(OperationLogRepository logRep)
    {
        _logRep = logRep;
    }

    public Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        if (context.ActionDescriptor.EndpointMetadata.Any(a => a.GetType() == typeof(NoLogAttribute)))
        {
            return next();
        }
        return LogAsync(context, next);
    }

    private async Task LogAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        var sw = new Stopwatch();
        sw.Start();
        var actionResult = (await next()).Result;
        sw.Stop();

        var args = context.ActionArguments.ToJson();
        var result = actionResult?.ToJson();
        var request = BuilderExtensions.ServiceProvider.GetRequiredService<IHttpContextAccessor>().HttpContext?.Request;
        var ua = request?.Headers["User-Agent"];
        var client = UAParser.Parser.GetDefault().Parse(ua);
        var controller = ((ControllerActionDescriptor)context.ActionDescriptor).ControllerName.ToLower();
        var action = ((ControllerActionDescriptor)context.ActionDescriptor).ActionName.ToLower();

        var log = new OperationLog
        {
            ApiMethod = context.HttpContext.Request.Method.ToLower(),
            ApiPath = $"/{controller}/{action}",
            ElapsedMilliseconds = sw.ElapsedMilliseconds,
            Params = args,
            Result = result,
            Browser = client.UA.ToString(),
            Os = client.OS.ToString(),
            Device = client.Device.ToString(),
            BrowserInfo = ua,
            IP = CommonFun.GetIP(request)
        };
        //自动分表插入
        await _logRep.AddSplitTableAsync(log);
    }
}

此处我们使用Sqlsugar的自动分表功能来实现分表插入,当然根据你的日志量大小用单表也可以实现。

3、我们新建一个Attribute用来标记需要记录日志的操作或者不需要记录日志的操作,此处我们新建一个不记录的NoLogAttribute:

namespace NET6.Api.Attributes;

/// <summary>
/// 不记录操作日志
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class NoLogAttribute : Attribute
{

}

4、一切准备就绪,我们那将这两个过滤器添加到Program中:

// Add services to the container.
builder.Services.AddControllersWithViews(options =>
{
    options.Filters.Add<LogActionFilter>();
    options.Filters.Add<GlobalExceptionFilter>();
})

5、我们将NoLogAttribute随意放置到一个Action上,然后启动项目,访问接口会发现,除了我们放置NoLogAttribute的那个方法,其他请求都已经成功生成日志:
在这里插入图片描述
6、我们在Auth的Loin方法中抛出一个异常:
在这里插入图片描述
请求接口发现异常已经按照Json格式成功抛出
在这里插入图片描述

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值