ASP.NET Core 异常处理与日志记录
1.1. 异常处理
1.1.1. 异常产生的原因及处理
异常是在编程时,一个意外的事件,如无效的输入或连接丢失,当程序执行破坏的指令流时就会出现这种情况。Exception是Exceptional event的简要表达。异常的实现需要保存抛出异常捕获点的必要信息,这会一定程度上导致程序变慢,这也是人们诟病异常性能的原因。
异常(Exception)是一种非程序原因的操作失败,而错误(Error)则意味着程序有缺陷。
Exception是一种类.例外会中断执行堆栈直到被捕获.一个异常可以用来传达一个错误,但是更普遍的是用来表示出现了一些例外.
1.1.2. ASP.NET Core中启动开发人员异常页面
想要在应用程序中显示详细的异常信息,展示错误详情的页面在Microsoft.AspNetCore.Diagnostics
包中,但是自从ASP.NET Core 2.0开始Microsoft.AspNetCore.All
包里面包含了所有以Microsoft.AspNetCore
开头的包,所以不需要在额外安装Microsoft.AspNetCore.Diagnostics
包,但是需要在Startup
类的Configure
方法中进行配置
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
env.EnvironmentName = EnvironmentName.Production;
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/error");
}
将UseDeveloperExceptionPage
放在你想捕获的中间件之前,如app.UseMvc
。
注:为了应用程序的安全,一般不会在生产环境中启起用开发者页面(异常页面)。
示例
HomeController.cs 手动抛出一个异常
public class HomeController : Controller
{
public IActionResult Index()
{
throw new Exception("dddd");
return View();
}
}
运行结果
这样的错误提示是很难让开发人员定位出错的位置;若要展示开发者页面,还需要将应用程序环境设置为Development
。
开发者页面有几个标签页面包含了异常信息和请求参数的信息:
堆栈的详细、查询参数、Cookies信息和请求头这些打印出来方便开发人员快速定位错误。但是程序在开发的时候可以直接这样定位出错位置,但是在生产环境中就需要借助日志将出错信息写到日志文件里面以方便开发人员定位错误。
1.2. 日志记录
1.2.1. 日志作用
程序中记录日志一般有两个目的,故障定位和显示程序运行状态。好的日志记录方式可以提供足够多定位问题的依据。
1.2.2. 日志等级
如果有良好的习惯的人平时工作的时候会将领导交待下来的工作分为:紧急重要、重要不紧急、紧急不重要、不紧急不重要等;同样ASP.NET Core也将日志定义了多个等级,从0到5总共6个等级:
- Trace = 0
这个级别只对开发人员调试有价值。这些消息可能包含敏感的应用程序数据,因此不应该在生产环境中启用。
- Debug = 1
对于在开发和调试过程中具有短期可用性的信息。如果不是出现问题在生产环境一般不建议启用。
- Information = 2
用于跟踪应用程序,这些日志有长期的价值。
- Warning = 3
用于程序中的异常或意外事件。这些可能包括错误或其他不导致应用程序停止的条件,但是可能需要进行排查。
- Error = 4
对于不能处理的错误过异常。这些消息表明当前的活动或操作(例如当前的HTTP请求)失败,而不是应用程序范围的失败。
- Critical = 5
对于那些需要立即关注的失败。示例:磁盘空间中的数据丢失场景。
开发人员可以根据日志级别将众多日志存储到不到的介质中,以供分析用户需求、定准程序错误等。
1.2.3. ASP.NET Core中的日志接口
ASP.NET Core支持可与各种日志记录提供程序配合使用的日志记录API。 内置提供程序允许您将日志发送到一个或多个目标,并且可以插入第三方日志记录框架。
1.2.4. 实践
用.NET Core内置日志接口将日志信息打印到控制台上
public class Startup
{
...
public virtual void Configure(IApplicationBuilder app)
{
...
app.UseExceptionHandler("/Home/Error");
...
}
}
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.Extensions.Logging;
public class HomeController : Controller
{
private readonly ILogger _logger;
public HomeController (ILogger<HomeController> logger) {
_logger = logger;
}
public IActionResult Index () {
throw new Exception ("dddd");
return View ();
}
public IActionResult Error()
{
var feature = HttpContext.Features.Get<IExceptionHandlerFeature>();
var error = feature?.Error;
_logger.LogError("Oops!Error Info-----:", error);
return View("~/Views/Shared/Error.cshtml", error);
}
}
Program.cs
public class Program {
public static void Main (string[] args) {
BuildWebHost (args).Run ();
}
public static IWebHost BuildWebHost (string[] args) =>
WebHost.CreateDefaultBuilder (args)
.UseContentRoot (Directory.GetCurrentDirectory ())
.ConfigureAppConfiguration ((hostingContext, config) => {
var env = hostingContext.HostingEnvironment;
config.AddJsonFile ("appsettings.json", optional : true, reloadOnChange : true)
.AddJsonFile ($"appsettings.{env.EnvironmentName}.json", optional : true, reloadOnChange : true);
config.AddEnvironmentVariables ();
})
.ConfigureLogging ((hostingContext, logging) => {
logging.AddConfiguration (hostingContext.Configuration.GetSection ("Logging"));
logging.AddConsole ();
logging.AddDebug ();
})
.UseStartup<Startup> ()
.Build ();
}
通过ASP.NET Core内置的日志支持可以很轻松将日志打印到控制台上面
注:
IExceptionHandlerFeature
接口位于Microsoft.AspNetCore.Diagnostics
包下,所以需要引入Microsoft.AspNetCore.Diagnostics
;ILogger
接口定义在Microsoft.Extensions.Logging.Abstractions
包,并且默认实现在Microsoft.Extensions.Logging
包里面。
但是,在生产环境中日志是记录在数据库或文件当中,下面以log4net作为例子将日志记录到文件当中。
log4net 保存日志
在选择log4net的时候最好选择最新版,log4net从2.0.6开始支持.NET Core。
- 安装log4net
执行dotnet restore
命令将nuget包拉到本地。确定本地.nuget文件夹里面有log4net并且版本号也一致。
- 配置log4net.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<!-- This section contains the log4net configuration settings -->
<log4net>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout" value="%date [%thread] %-5level %logger - %message%newline" />
</appender>
<appender name="FileAppender" type="log4net.Appender.FileAppender">
<param name="Encoding" value="utf-8" />
<file value="log-file.log" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender>
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<param name="Encoding" value="utf-8" />
<file value="logfile/" />
<appendToFile value="true" />
<rollingStyle value="Composite" />
<staticLogFileName value="false" />
<datePattern value="yyyyMMdd'.log'" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="1MB" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender>
<!-- Setup the root category, add the appenders and set the default level -->
<root>
<level value="ALL" />
<appender-ref ref="ConsoleAppender" />
<appender-ref ref="FileAppender" />
<appender-ref ref="RollingLogFileAppender" />
</root>
</log4net>
</configuration>
这里定义了三个appender,都会起作用;日志等级为ALL将会记录所有类型的日志。
Startup.cs
using System.IO;
using log4net;
using log4net.Config;
using log4net.Repository;
public class Startup
{
public static ILoggerRepository Repository;
public Startup (IHostingEnvironment env) {
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
Repository = LogManager.CreateRepository ("NETCoreRepository");
XmlConfigurator.Configure (Repository, new FileInfo ("log4net.config"));
}
HomeController.cs
public class HomeController : Controller {
private ILog log = LogManager.GetLogger (Startup.Repository.Name, typeof (HomeController));
public IActionResult Index () {
throw new Exception ("Manul Exception:");
return View ();
}
public IActionResult Error () {
var feature = HttpContext.Features.Get<IExceptionHandlerFeature> ();
var error = feature?.Error;
log.Error(error);
return View ("~/Views/Shared/Error.cshtml", error);
}
}
运行结果
访问首页时会出异常,根据跳转到错误路由Error
方法中;同时在项目中会生成两个文件:
FileAppender生成的log-file.log日志文件
RollingLogFileAppender 是按时间生成的日志文件
控件台打印出来的日志文件
RollingLogFileAppender 打印的日志文件
FileAppender打段日志文件
从上面来看三种Appender打印的三种日志是一致的,所以在实际开发的时候可以根据需要来用哪种方式进行记录日志。
1.3. 总结
本节讲解了两个知识点:
- 异常产生及异常和错误的区别,在ASP.NET Core中捕获异常,启动开发者异常页面。
- ASP.NET Core内置日志接口和使用log4net将异常日志输出到文件中
参与资料:
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/error-handling
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/?tabs=aspnetcore2x
http://logging.apache.org/log4net/release/manual/configuration.html
作者:xdpie 出处: http://www.cnblogs.com/vipyoumay/p/7838069.html
ASP.NET Core 异常处理与日志记录的更多相关文章
- (14)ASP.NET Core 中的日志记录
1.前言 ASP.NET Core支持适用于各种内置和第三方日志记录提供应用程序的日志记录API.本文介绍了如何将日志记录API与内置提供应用程序一起使用. 2.添加日志提供程序 日志记录提供应用程序 ...
- ASP.NET Core 中的日志记录
目录 内置日志的使用 使用Nlog 集成ELK 参考 内置日志的使用 Logger 是 asp .net core 的内置 service,所以我们就不需要在ConfigureService里面注册了 ...
- asp.net core 系列 13 日志
一.概述 ASP.NET Core 支持适用于各种内置和第三方日志记录, 供程序的日志记录 API,本文介绍了如何将日志记录 API 与内置提供程序一起使用.对于第三方日志记录提供程序使用,文章最后有 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - 异常处理和日志记录
在开始之前,我们实现一个之前的遗留问题,这个问题是有人在GitHub Issues(https://github.com/Meowv/Blog/issues/8)上提出来的,就是当我们对Swagger ...
- ASP.NET Core 1.0 开发记录
官方资料: https://github.com/dotnet/core https://docs.microsoft.com/en-us/aspnet/core https://docs.micro ...
- 玩转ASP.NET Core中的日志组件
简介 日志组件,作为程序员使用频率最高的组件,给程序员开发调试程序提供了必要的信息.ASP.NET Core中内置了一个通用日志接口ILogger,并实现了多种内置的日志提供器,例如 Console ...
- asp.net core 集成 log4net 日志框架
asp.net core 集成 log4net 日志框架 Intro 在 asp.net core 中有些日志我们可能想输出到数据库或文件或elasticsearch等,如果不自己去实现一个 Logg ...
- 观看杨老师(杨旭)Asp.Net Core MVC入门教程记录
观看杨老师(杨旭)Asp.Net Core MVC入门教程记录 ASP.NET Core MVC入门 Asp.Net Core启动和配置 Program类,Main方法 Startup类 依赖注入,I ...
- 第七节:Asp.Net Core内置日志和整合NLog(未完)
一. Asp.Net Core内置日志 1. 默认支持三种输出方式:控制台.调试(底部输出窗口).EventSource,当然也可以在Program类中通过logging.ClearProviders ...
随机推荐
- C-多个行内块布局
1 消除间隔
- IDL 结构体
1.创建结构体 (1) 命名结构体 创建具有两个成员变量A.B的命名为str1的结构体 IDL> struct1={str1,a:1,b:2} IDL> help,struct1,/str ...
- 学习笔记之08试用div做网页(滨院)-小作业
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Activiti 用户任务关联自定义表单
问题阐述 通常每一个"用户任务"都会对应一个表单,以供用户录入信息.尤其是在"流程定义"拥有多个版本的情形下,明确的指定表单显得极其重要. 一份新版本的&quo ...
- hadoop之 hadoop 2.2.X 弃用的配置属性名称及其替换名称对照表
Deprecated Properties 弃用属性 The following table lists the configuration property names that are depr ...
- bind、apply与call
bind.apply与call 先说观点:不论是bind.apply还是call,最大的好处就是代码复用. bind 在开发中,我们只有复用代码时,才会出现this指向需要改动的情况. 纵观bind的 ...
- 安装debian 9.1后,中文环境下将home目录下文件夹改为对应的英文
安装了debian 9.1后,中文环境下home目录下文件夹显示的是中文,相当不方便cd命令,改为对应的英文吧,需要用到的软件xdg-user-dirs-gtk #安装需要的软件 sudo apt i ...
- 笨鸟先飞之ASP.NET MVC系列之过滤器(06异常过滤器)
概念介绍 异常过滤器主要在我们方法中出现异常的时候触发,一般我们用 异常过滤器 记录日志,或者在产生异常时做友好的处理 如果我们需要创建异常过滤器需要实现IExceptionFilter接口. nam ...
- sublime中安装package control总是失败
今天下载了个sublime编辑器,要运行vue文件,想让vue也能高亮显示,在网上搜了一下如何安装.但总是提示控制器没有安装Package Control:There are no packages ...
- Vue源码后记-vFor列表渲染(3)
这一节肯定能完! 经过DOM字符串的AST转化,再通过render变成vnode,最后就剩下patch到页面上了. render函数跑完应该是在这里: function mountComponent( ...