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结构化日志,可以更好的完成日志分析

相关推荐
愤怒的代码12 分钟前
Spring Boot对访问密钥加解密——HMAC-SHA256
java·spring boot·后端
栗豆包28 分钟前
w118共享汽车管理系统
java·spring boot·后端·spring·tomcat·maven
万亿少女的梦16840 分钟前
基于Spring Boot的网络购物商城的设计与实现
java·spring boot·后端
开心工作室_kaic2 小时前
springboot485基于springboot的宠物健康顾问系统(论文+源码)_kaic
spring boot·后端·宠物
0zxm2 小时前
08 Django - Django媒体文件&静态文件&文件上传
数据库·后端·python·django·sqlite
刘大辉在路上9 小时前
突发!!!GitLab停止为中国大陆、港澳地区提供服务,60天内需迁移账号否则将被删除
git·后端·gitlab·版本管理·源代码管理
追逐时光者11 小时前
免费、简单、直观的数据库设计工具和 SQL 生成器
后端·mysql
初晴~12 小时前
【Redis分布式锁】高并发场景下秒杀业务的实现思路(集群模式)
java·数据库·redis·分布式·后端·spring·
盖世英雄酱5813612 小时前
InnoDB 的页分裂和页合并
数据库·后端