aspnetcore配置log4net并添加全局异常处理
第一步:在NuGet中引用log4net
第二步:创建log4net.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<log4net>
<!-- 错误日志类-->
<logger name="Error">
<level value="ALL" />
<appender-ref ref="ErrorAppender" />
</logger>
<!-- 错误日志附加介质-->
<appender name="ErrorAppender" type="log4net.Appender.RollingFileAppender">
<!--日志文件路径-->
<param name="File" value="Logs\\Error\\" />
<!--是否是向文件中追加日志-->
<param name="AppendToFile" value="true" />
<!--log保留天数-->
<param name="MaxSizeRollBackups" value="1000" />
<!--最大文件大小-->
<param name="MaxFileSize" value="10240" />
<!--日志文件名是否是固定不变的-->
<param name="StaticLogFileName" value="false" />
<!--日志文件名格式为:2008-08-31.log-->
<param name="DatePattern" value="yyyy-MM-dd.'log'" />
<!--日志根据日期滚动-->
<param name="RollingStyle" value="Date" />
<!--信息日志布局-->
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%n==========%n【日志级别】:%-5level%n【记录时间】:%date %n【执行时间】:[%r]毫秒%n%message%n" />
</layout>
</appender> <!-- 信息日志类 -->
<logger name="Info">
<level value="ALL" />
<appender-ref ref="InfoAppender" />
</logger>
<!-- 信息日志附加介质-->
<appender name="InfoAppender" type="log4net.Appender.RollingFileAppender">
<!--日志文件路径-->
<param name="File" value="Logs\\Info\\" />
<!--是否是向文件中追加日志-->
<param name="AppendToFile" value="true" />
<!--log保留天数-->
<param name="MaxSizeRollBackups" value="100" />
<param name="MaxFileSize" value="1" />
<!--日志文件名是否是固定不变的-->
<param name="StaticLogFileName" value="false" />
<!--日志文件名格式为:2008-08-31.log-->
<param name="DatePattern" value="yyyy-MM-dd.'log'" />
<!--日志根据日期滚动-->
<param name="RollingStyle" value="Date" />
<!--信息日志布局-->
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%n==========%n【日志级别】:%-5p%n【记录时间】:%d [%t]%n【信息详情】:%m%n" />
</layout>
</appender>
</log4net>
</configuration>
第三步:新建Log4NetConfig.cs类,这里我是把工厂名放在配置文件中获取,一般情况下不需要这样操作,直接在代码内写死即可。
using log4net;
using log4net.Config;
using Microsoft.Extensions.Configuration;
using System;
using System.IO; namespace Taoxue.SchoolRoll.Website
{
public class Log4NetConfig
{
public static string RepositoryName { get; set; } public static void Init(IConfiguration configuration)
{
var repositoryName = configuration.GetSection("Log4Net:RepositoryName").Value;
if (string.IsNullOrWhiteSpace(repositoryName))
{
throw new Exception("必须在配置文件中添加 Log4Net > RepositoryName 节点");
} RepositoryName = repositoryName; var configFilePath = configuration.GetSection("Log4Net:ConfigFilePath").Value;
if (string.IsNullOrWhiteSpace(configFilePath))
{
configFilePath = "log4net.config";
} var file = new FileInfo(configFilePath);
var repository = LogManager.CreateRepository(repositoryName);
XmlConfigurator.Configure(repository, file);
}
}
}
第四步:在startup.cs中初始化配置
public Startup(IConfiguration configuration)
{
Configuration = configuration;
Log4NetConfig.Init(Configuration);
}
第五步:在appsettings.json中创建Log4net节点,注意,这里我是把log4net.config放在 站点根目录/Log4Net 目录下
"Log4Net": {
"RepositoryName": "NETCoreRepository",
"ConfigFilePath": "Log4Net/log4net.config"
}
第六步:创建Log4NetUtil.cs文件
using log4net;
using System; namespace Taoxue.SchoolRoll.Website
{
public class Log4NetUtil
{
private static readonly ILog ErrorLog = LogManager.GetLogger(Log4NetConfig.RepositoryName, "Error"); private static readonly ILog InfoLog = LogManager.GetLogger(Log4NetConfig.RepositoryName, "Info"); /// <summary>
/// 全局异常错误记录持久化
/// </summary>
/// <param name="throwMsg"></param>
/// <param name="ex"></param>
public static void LogError(string throwMsg, Exception ex)
{
var errorMsg =
$"【抛出信息】:{throwMsg} \r\n【异常类型】:{ex.GetType().Name} \r\n【异常信息】:{ex.Message} \r\n【堆栈调用】:\r\n{ex.StackTrace}";
ErrorLog.Error(errorMsg);
} public static void LogInfo(string msg)
{
InfoLog.Info(msg);
}
}
}
至此,Log4Net配置完成,下面添加一个全局异常处理类测试下
using HZC.Core;
using HZC.Utils.Mvc;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System; namespace Taoxue.SchoolRoll.Website.Extensions
{
public class MvcGlobalExceptionFilter : IExceptionFilter
{
public void OnException(ExceptionContext context)
{
try
{
Log4NetUtil.LogError("Mvc全局异常", context.Exception);
if (context.HttpContext.Request.IsAjax())
{
context.Result = new JsonResult(ResultUtil.Fail(context.Exception.Message));
}
else
{
context.Result = new RedirectToActionResult("Error", "Home", new { });
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
context.ExceptionHandled = true; // 注意:如果不添加这句代码,程序不会自动断路,会继续向下进行。
}
}
}
在 startup.cs 的 ConfigureServices 中使用如下代码
services.AddMvc(option =>
{
option.Filters.Add<MvcGlobalExceptionFilter>();
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
修改 HomeController 的 Index ,手动抛出异常
public IActionResult Index()
{
throw new Exception("异常测试");
return View();
}
执行程序,在 根目录/Logs/Error 文件夹下查看生成的日志文件,发现已经写入如下内容
==========
【日志级别】:ERROR
【记录时间】:2019-05-16 00:40:49,071
【执行时间】:[1750]毫秒
【抛出信息】:Mvc全局异常
【异常类型】:Exception
【异常信息】:异常测试
【堆栈调用】:
at Taoxue.SchoolRoll.Website.Controllers.HomeController.Index() in E:\项目\CSharp\xx\xxxx\Taoxue.SchoolRoll.Website\Controllers\HomeController.cs:line 19
at lambda_method(Closure , Object , Object[] )
at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync()
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextExceptionFilterAsync()
到这里,log4net配置和全局异常捕捉就完成了。
需要注意的是,这里所谓的全局是指进入mvc中间件后产生的异常,如果在其他中间件中异常了,上面的方法是捕捉不到的,下面来模拟一下:
在 startup.cs 的 Configure 方法中 app.UserMvc(...) 之前添加如下代码
app.Use(async (context, next) =>
{
if (context.Request.Path.Value.Contains("test"))
{
throw new Exception("中间件异常测试");
}
await next();
});
上面代码的作用是,当访问地址中带有 test 则抛出异常。
执行程序,访问 http://localhost:5000/test 会发现,程序报错,这时查看日志会发现,异常并没有被记录,也就是说,异常没有被我们的MvcGlobalExceptionFilter捕捉到,这显然不是我们想要的。
如果要捕捉到这种异常需要怎么处理呢?其实程序中已经给出了提示:
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
这是 startup.cs Configure 中自动帮我们添加的代码,就是用于异常的捕获和处理,一种方式是对 /Home/Error 进行处理,在该action内记录异常,这种方法比较简单,这里就不详细说了。
接下来,我们用自定义中间件的方式来实现一下。
新建 GlobalExceptionMiddleware.cs 文件
using HZC.Core;
using HZC.Utils.Mvc;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System;
using System.Threading.Tasks; namespace Taoxue.SchoolRoll.Website.Extensions
{
public class GlobalExceptionMiddleWare
{
public readonly RequestDelegate Next; public GlobalExceptionMiddleWare(RequestDelegate next)
{
Next = next;
} public async Task Invoke(HttpContext context)
{
try
{
await Next(context);
}
catch (Exception e)
{
context.Response.Clear();
context.Response.StatusCode = StatusCodes.Status200OK; Log4NetUtil.LogError("全局异常", e); if (context.Request.IsAjax())
{
context.Response.ContentType = ResponseContentTypes.Json;
await context.Response.WriteAsync(JsonConvert.SerializeObject(new { Code = 500, Message = e.Message }));
}
else
{
context.Response.Redirect("/Home/Error");
}
}
}
}
}
建议在 Invoke 方法中 catch 代码块中再包一层 try..catch ,以防止处理代码发生错误时出现异常。
接下来,修改 startup.cs 的 Configure 方法,注释掉系统自带的异常处理代码,添加我们自定义的中间件
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//if (env.IsDevelopment())
//{
// app.UseDeveloperExceptionPage();
//}
//else
//{
// app.UseExceptionHandler("/Home/Error");
// app.UseHsts();
//}
app.UseMiddleware<GlobalExceptionMiddleWare>(); app.Use(async (context, next) =>
{
if (context.Request.Path.Value.Contains("test"))
{
throw new Exception("中间件异常测试");
}
await next();
}); app.UseHttpsRedirection();
app.UseStaticFiles(); app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
再次执行程序,访问 http://localhost:5000/test 会发现我们定义的逻辑被执行,并且该异常也被记录到了日志文件中
==========
【日志级别】:ERROR
【记录时间】:-- ::,
【执行时间】:[]毫秒
【抛出信息】:全局异常
【异常类型】:Exception
【异常信息】:中间件异常测试
【堆栈调用】:
at Taoxue.SchoolRoll.Website.Startup.<>c.<<Configure>b__5_0>d.MoveNext() in E:\项目\CSharp\xx\xxxx\Taoxue.SchoolRoll.Website\Startup.cs:line
--- End of stack trace from previous location where exception was thrown ---
at Taoxue.SchoolRoll.Website.Extensions.GlobalExceptionMiddleWare.Invoke(HttpContext context) in E:\项目\CSharp\xx\xxxx\Taoxue.SchoolRoll.Website\Extensions\GlobalExceptionMiddleWare.cs:line
aspnetcore配置log4net并添加全局异常处理的更多相关文章
- asp.net core添加全局异常处理及log4net、Nlog应用
0.目录 整体架构目录:ASP.NET Core分布式项目实战-目录 一.介绍 此篇文章将会介绍项目的全局异常收集以及采用log4net或者NLog记录. 众所周知,一旦自己的项目报错,如果没有进行处 ...
- 单元测试中如何配置log4net
按道理来说,单元测试中基本没有对于日志的需求,这是由于单元测试的定位来决定的. 因为单元测试的思想就是针对的都是小段代码的测试,逻辑明确,如果测试运行不通过,简单调试一下,就能很容易地排查问题.但是单 ...
- 【springboot】全局异常处理
转自: https://blog.csdn.net/cp026la/article/details/86495196 前言: 开发中异常的处理必不可少,常用的就是 throw 和 try catch, ...
- ASP.NET Core 中间件的使用(三):全局异常处理机制
前言 我们经常听到"秒修复秒上线",觉得很厉害的样子. 其实不然,这只是一个调侃而已,出现问题的方式很多(逻辑漏洞.代码异常.操作方式不正确等). 我们今天来说代码异常问题怎么快速 ...
- MVC 全局异常处理及禁用显示头
MVC网站的global.asax中的Application_Start方法里,有这样一段代码: public class MvcApplication : System.Web.HttpApplic ...
- AspNetCore配置多环境log4net配置文件
前言 在之前的文章中有讲到AspNetCore多环境配置文件的应用,我们根据自己多种环境分别配置多个appsettings.$EnvironmentName.json文件. 在实际的开发中我们可能会遇 ...
- jenkins系列之添加全局配置(一)
第一步: 第二步:执行以下命令: 第三步:找到/c/Users/Administrator/.ssh 目录,里面有两个文件:id_rsa和id_rsa.pub 第四步:配置ssh[这里是id_rsa. ...
- mvc自定义全局异常处理
异常信息处理是任何网站必不可少的一个环节,怎么有效显示,记录,传递异常信息又成为重中之重的问题.本篇将基于上篇介绍的html2cancas截图功能,实现mvc自定义全局异常处理.先看一下最终实现效果: ...
- .NET MVC全局异常处理(二)
目录 .NET MVC全局异常处理(二) MVC过滤器Filter .NET MVC全局异常处理(二) 对上节的内容进行了补充 MVC过滤器Filter MVC有四种过滤器:Authorization ...
随机推荐
- 在Debug中使用断点调试程序
我最近在学习汇编的程序,所以很多都需要动手写点代码去测试,如果是测试三五行代码的还比较简单,可以在debug中直接按T进行单步调试,但是到后来调试的代码越来越复杂,越来越长,如果再使用单步调试不知道要 ...
- bzoj 1070 修车 —— 费用流
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1070 需要考虑前面修的车对后面等待的车造成的时间增加: 其实可以从每个人修车的顺序考虑,如果 ...
- nefu26(求数的位数)
Description 根据密码学需要,要计算某些数的阶乘的位数. Input 第一行为整数n ,接下来 n 行, 每行1个数m (1 ≤ m ≤ 10^7) . Output 输出m的阶乘的位数. ...
- C++11中的原子操作(atomic operation)
所谓的原子操作,取的就是“原子是最小的.不可分割的最小个体”的意义,它表示在多个线程访问同一个全局资源的时候,能够确保所有其他的线程都不在同一时间内访问相同的资源.也就是他确保了在同一时刻只有唯一的线 ...
- DDoS攻防战(二):CC攻击工具实现与防御理论--删除
我们将要实现一个进行应用层DDoS攻击的工具,综合考虑,CC攻击方式是最佳选择,并用bash shell脚本来快速实现并验证这一工具,并在最后,讨论如何防御来自应用层的DDoS攻击. 第一步:获取大量 ...
- Java学习路线-知乎
鼬自来晓 378 人赞同 可以从几方面来看Java:JVM Java JVM:内存结构和相关参数含义 · Issue #24 · pzxwhc/MineKnowContainer · GitHub J ...
- Java探索之旅(4)——方法和Random&Math类
1.基本知识点 ❶方法在C++里面称为函数.调用方法时,应该类型兼容--即不需显式类型转换即可将形参传递给实参. ❷形参的改变不影响实参的值. ❸Java注重模块化设计和自顶向下的设 ...
- ls- 查看文件信息
通过ls 命令不仅可以查看linux文件夹包含的文件,而且可以查看文件权限(包括目录.文件夹.文件权限),查看目录信息等等,ls 命令在日常的linux操作中用的很多,在此给大家介绍一下ls 命令的使 ...
- VS 关于无法打开项目文件,此安装不支持该项目类型的问题
用VS打开后有时会出现类似: 无法打开项目文件,此安装不支持该项目类型 的错误,这个错误一般都是由于用低版本VS打开高版本项目文件造成的 其中包括: 1.用VS2003 打开包括VS2005以上版本项 ...
- nodejs中 underscore 包有什么作用
Underscore一个JavaScript实用库,提供了一整套函数式变成有用的实用功能,但是没有扩展任何JavaScript内置对象.它是这个问题的答案:“如果我在一个空白的HTML页面前坐下, 并 ...