asp.net core自定义异常过滤器并记录到Log4Net日志

1.创建异常过滤器特性

csharp 复制代码
using Log4Net.Controllers;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace Log4NetTest
{
    public class CustomerExceptionFilterAttribute : Attribute, IExceptionFilter
    {
        private readonly ILogger<CustomerExceptionFilterAttribute> _logger;

        public CustomerExceptionFilterAttribute(ILogger<CustomerExceptionFilterAttribute> logger)
        {
            _logger = logger;
        }

        //当发生异常时,执行方法
        public void OnException(ExceptionContext context)
        {
            //可以把错误信息写道日志里面
            _logger.LogError(context.Exception.Message);
            context.Result = new JsonResult(new
            {
                Success = false,
                Msg = context.Exception.Message,
                Position = context.Exception.StackTrace,
                Data = context.RouteData.Values
            });
        }
    }
}

2.使用异常特性

模拟一个报错,除数不为0

csharp 复制代码
  /// <summary>
        /// 退出
        /// </summary>
        [HttpGet]
        [TypeFilter(typeof(CustomerExceptionFilterAttribute))]
        public async Task<IActionResult> Test()
        {
            int i = 0;
            int j = 1 / i;//
            return Ok();
        }

TypeFilter:是把CustomerExceptionFilterAttribute注入到服务,

ServiceFilter:这里也可以使用ServiceFilter,然后在program中注入 builder.Services.AddScoped();

也可以全局注入,就不需要在控制器或方法上使用特性了

csharp 复制代码
 builder.Services.AddControllers(options =>
            {
                //全局
                options.Filters.Add<CustomerExceptionFilterAttribute>(); // 注册自定义异常过滤器
            });

执行后会返回下面的效果

3.配置Log4Net日志

3.1安装Nuget包

csharp 复制代码
<PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="6.1.0" />
<PackageReference Include="log4net" Version="2.0.14" />

3.2创建log4Net的config配置文件

csharp 复制代码
<?xml version="1.0" encoding="utf-8"?>
<log4net>
  <!-- Define some output appenders -->
  <appender name="rollingAppender" type="log4net.Appender.RollingFileAppender">
    <!--    value="logs/log.log"-->
    <file value="logs/" />
    <!--追加日志内容-->
    <appendToFile value="true" />

    <!--防止多线程时不能写Log,官方说线程非安全-->
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />

    <!--可以为:Once|Size|Date|Composite-->
    <!--Composite为Size和Date的组合-->
    <rollingStyle value="Composite" />

    <!--当备份文件时,为文件名加的后缀-->
    <datePattern value="yyyyMMdd/'log.log'" />

    <!--日志最大个数,都是最新的-->
    <!--rollingStyle节点为Size时,只能有value个日志-->
    <!--rollingStyle节点为Composite时,每天有value个日志-->
    <maxSizeRollBackups value="20" />

    <!--可用的单位:KB|MB|GB-->
    <maximumFileSize value="3MB" />

    <!--置为true,当前最新日志文件名永远为file节中的名字-->
    <staticLogFileName value="false" />

    <!--输出级别在INFO和ERROR之间的日志-->
    <filter type="log4net.Filter.LevelRangeFilter">
      <param name="LevelMin" value="ALL" />
      <param name="LevelMax" value="FATAL" />
    </filter>
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
    </layout>
  </appender>
  <!-- error日志 -->
  <appender name="errorAppender" type="log4net.Appender.RollingFileAppender">
    <file value="logs/" />
    <appendToFile value="true" />
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
    <rollingStyle value="Composite" />
    <datePattern value="yyyyMMdd/'error.log'" />
    <maxSizeRollBackups value="20" />
    <maximumFileSize value="3MB" />
    <staticLogFileName value="false" />
    <filter type="log4net.Filter.LevelRangeFilter">
      <param name="LevelMin" value="ERROR" />
      <param name="LevelMax" value="ERROR" />
    </filter>
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
    </layout>
  </appender>
  <!--SqlServer形式-->
  <!--log4net日志配置:http://logging.apache.org/log4net/release/config-examples.html -->
  <appender name="mysqlAppender" type="log4net.Appender.AdoNetAppender">
    <!--日志缓存写入条数 设置为0时只要有一条就立刻写到数据库-->
    <bufferSize value="0" />
    <connectionType value="System.Data.SqlClient.SqlConnection,System.Data" />
    <!--日志数据库连接串-->
    <connectionString value="server=.;database=zhaoxi;uid=sa;pwd=peng@123" />

    <commandText value="INSERT INTO logs(app_name,log_date, thread, level, logger, message,exception)VALUES(@app_name,@log_date, @thread,@log_level, @logger, @message, @exception);" />
    <parameter>
      <parameterName value="@app_name" />
      <dbType value="String" />
      <size value="100" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="api" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@log_date" />
      <dbType value="DateTime" />
      <layout type="log4net.Layout.RawTimeStampLayout" />
    </parameter>
    <parameter>
      <parameterName value="@thread" />
      <dbType value="String" />
      <size value="100" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%thread" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@log_level" />
      <dbType value="String" />
      <size value="50" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%level" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@logger" />
      <dbType value="String" />
      <size value="255" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%logger" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@message" />
      <dbType value="String" />
      <size value="1000" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%message" />
      </layout>
    </parameter>
    <parameter>
      <parameterName value="@exception" />
      <dbType value="String" />
      <size value="2000" />
      <layout type="log4net.Layout.ExceptionLayout" />
    </parameter>
  </appender>
  <root>

    <!--控制级别,由低到高: ALL|DEBUG|INFO|WARN|ERROR|FATAL|OFF-->
    <!--OFF:0-->
    <!--FATAL:FATAL-->
    <!--ERROR: ERROR,FATAL-->
    <!--WARN: WARN,ERROR,FATAL-->
    <!--INFO: INFO,WARN,ERROR,FATAL-->
    <!--DEBUG: INFO,WARN,ERROR,FATAL-->
    <!--ALL: DEBUG,INFO,WARN,ERROR,FATAL-->
    <priority value="ALL" />

    <level value="INFO" />
    <!--使用上面配置的那个规则,ref指定上面的规则名称-->
    <appender-ref ref="rollingAppender" />
    <appender-ref ref="errorAppender" />
    <appender-ref ref="mysqlAppender" />
  </root>
</log4net>

3.2注入日志服务

csharp 复制代码
  builder.Logging.AddLog4Net("Configs/log4net.Config");

这样就把日志写到了error.log.txt文件里了

补充:log4Net是对asp.net core 自带的日志系统的包装,已完成更多的日志功能,这边也可以写入到数据库等,也可以接入serilog结构化日志,可以更好的完成日志分析

相关推荐
wowocpp2 小时前
spring boot Controller 和 RestController 的区别
java·spring boot·后端
后青春期的诗go2 小时前
基于Rust语言的Rocket框架和Sqlx库开发WebAPI项目记录(二)
开发语言·后端·rust·rocket框架
freellf2 小时前
go语言学习进阶
后端·学习·golang
全栈派森4 小时前
云存储最佳实践
后端·python·程序人生·flask
CircleMouse4 小时前
基于 RedisTemplate 的分页缓存设计
java·开发语言·后端·spring·缓存
獨枭5 小时前
使用 163 邮箱实现 Spring Boot 邮箱验证码登录
java·spring boot·后端
维基框架5 小时前
Spring Boot 封装 MinIO 工具
java·spring boot·后端
秋野酱5 小时前
基于javaweb的SpringBoot酒店管理系统设计与实现(源码+文档+部署讲解)
java·spring boot·后端
☞无能盖世♛逞何英雄☜6 小时前
Flask框架搭建
后端·python·flask
进击的雷神6 小时前
Perl语言深度考查:从文本处理到正则表达式的全面掌握
开发语言·后端·scala