为了减少系统中通过try catch来捕获异常的重复工作,在.net Core中用过异常过滤器来捕获全局异常,并通过Log4Net记录所有的错误日志
一.Log4Net安装和使用
(1)引入Nuget包
Microsoft.Extensions.Logging.Log4Net.AspNetCore
(2)添加Log4Net配置文件
Log4Net.config
1 <?xml version="1.0" encoding="utf-8"?>
2 <log4net>
3 <!-- Define some output appenders -->
4 <appender name="rollingAppender" type="log4net.Appender.RollingFileAppender">
5 <file value="log\log.txt" />
6 <!--追加日志内容-->
7 <appendToFile value="true" />
8 <!--防止多线程时不能写Log,官方说线程非安全-->
9 <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
10 <!--可以为:Once|Size|Date|Composite-->
11 <!--Composite为Size和Date的组合-->
12 <rollingStyle value="Composite" />
13 <!--当备份文件时,为文件名加的后缀-->
14 <datePattern value="yyyyMMdd.TXT" />
15 <!--日志最大个数,都是最新的-->
16 <!--rollingStyle节点为Size时,只能有value个日志-->
17 <!--rollingStyle节点为Composite时,每天有value个日志-->
18 <maxSizeRollBackups value="20" />
19 <!--可用的单位:KB|MB|GB-->
20 <maximumFileSize value="3MB" />
21 <!--置为true,当前最新日志文件名永远为file节中的名字-->
22 <staticLogFileName value="true" />
23 <!--输出级别在INFO和ERROR之间的日志-->
24 <!--过滤级别 FATAL > ERROR > WARN > INFO > DEBUG-->
25 <filter type="log4net.Filter.LevelRangeFilter">
26 <param name="LevelMin" value="ALL" />
27 <param name="LevelMax" value="FATAL" />
28 </filter>
29 <layout type="log4net.Layout.PatternLayout">
30 <conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/>
31 </layout>
32 </appender>
33 <root>
34 <priority value="ALL"/>
35 <level value="Microsoft"/>
36 <appender-ref ref="rollingAppender" />
37 </root>
38 </log4net>
(3)
更改配置文件属性 Configure,注册中间件
loggerFactory.AddLog4Net();
(4)通过注入的方式使用
1 private readonly Frame_DeptService _service;
2 private readonly ILogger<FrameDeptController> _logger;
3 public FrameDeptController(Frame_DeptService service, ILogger<FrameDeptController> logger)
4 {
5 _service = service;
6 _logger = logger;
7 }
8 public IActionResult Index()
9 {
10 _logger.LogInformation("这是一个日志");
11 return View();
12 }
二.自定义异常过滤器
(1)
自定义一个异常过滤器需要继承接口IExceptionFilter或者ExceptionFilterAttribute
IExceptionFilter:
ExceptionFilterAttribute:
两者本质都是IExceptionFilter
但是ExceptionFilterAttribute增加了Order属性用于优先级处理,
以及OnExceptionAsync异步处理的方法,所以本次过滤器选择继承接口ExceptionFilterAttribute
(2)新建类
“HttpGlobalExceptionFilter.cs”
1 public class HttpGlobalExceptionFilter : ExceptionFilterAttribute
2 {
3 private readonly ILogger<HttpGlobalExceptionFilter> _logger;
4 public HttpGlobalExceptionFilter(ILogger<HttpGlobalExceptionFilter> logger)
5 {
6 _logger = logger;
7 }
8
9 public override void OnException(ExceptionContext context)
10 {
11
12 var actionName = context.HttpContext.Request.RouteValues["controller"] + "/" + context.HttpContext.Request.RouteValues["action"];
13 _logger.LogError($"--------{actionName} Error Begin--------");
14 _logger.LogError($" Error Detail:" + context.Exception.Message);
15 //拦截处理
16 if (!context.ExceptionHandled)
17 {
18 context.Result = new JsonResult(new TableData
19 {
20 status = false,
21 msg = context.Exception.Message
22 });
23 context.ExceptionHandled = true;
24 }
25 _logger.LogError($"--------{actionName} Error End--------");
26 }
27 }
通过步骤一中的Log4Net记录错误信息:
_logger.LogError($" Error Detail:" + context.Exception.Message);
(3)在“Startup.cs”的“ConfigureServices”中全局注册异常处理过滤器HttpGlobalExceptionFilter
1 services.AddMvc(
2 options =>
3 {
4 options.Filters.Add<HttpGlobalExceptionFilter>();//全局注册
5 });
(4)查看错误日志
在控制器中抛出一个异常,用于查看是否捕获异常
[HttpPost]
public string LoadDeptTree()
{
PageResponse resp = new PageResponse();
resp.Message = _service.LoadDeptTree();
throw new Exception("错误测试"); //return JsonHelper.Instance.Serialize(resp);
}
打开日志文件 log.text,捕获成功,如下图所示
三.日志优化
在log.text中,级别为Info的信息也会被写入,影响错误的查看,通过设置log级别过滤
在配置文件
log4net.config中,修改如下:
<param name="LevelMin" value="WARN" />
<param name="LevelMax" value="FATAL" />
重新打开log.text,如下:
|