asp.net core添加全局异常处理及log4net、Nlog应用

一、介绍


 

此篇文章将会介绍项目的全局异常收集以及采用log4net或者NLog记录。

众所周知,一旦自己的项目报错,如果没有进行处理都是显示不友好的,有得甚至直接爆出错误页面,看的也是很奇怪。

 为了避免出现这样的错误以及在错误出现的时候可以进行收集错误,供维护人员进行bug修改,因此需要进行全局异常的收集。

 让我们开始部署吧。 

此篇文章的目录

1、log4net使用

2、Nlog使用

后期将会把NLog+ELK进行结合部署收集我们的asp.net core的项目。大家可以拭目以待吧。 

二、部署(log4net使用)


 1、新建一个asp.net core webapi的项目

然后目前我先引入 log4net   nuget包。

640?wx_fmt=png

2、然后创建一个log4net.config文件

此文件中,我创建了一个是记录 错误的文件夹(LogError)以及是记录操作的文件夹(LogInfo),代码如下:我把需要记录的文件放在了log文件夹下面。

<?xml version="1.0" encoding="utf-8"?>

<configuration>

  <log4net>

    <!-- 错误日志类-->

    <logger name="logerror">

      <level value="ALL" />

      <appender-ref ref="ErrorAppender" />

    </logger>

    <!-- 错误日志附加介质-->

    <appender name="ErrorAppender" type="log4net.Appender.RollingFileAppender">

      <!--日志文件路径-->

      <param name="File" value="Log\\LogError\\" />

      <!--是否是向文件中追加日志-->

      <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&quot;.htm&quot;" />

      <!--日志根据日期滚动-->

      <param name="RollingStyle" value="Date" />

      <!--信息日志布局-->

      <layout type="log4net.Layout.PatternLayout">

        <param name="ConversionPattern" value="&lt;HR COLOR=red&gt;%n【异常时间】:%d [%t] &lt;BR&gt;%n【异常级别】:%-5p &lt;BR&gt;%n%m &lt;BR&gt;%n &lt;HR Size=1&gt;"  />

      </layout>

    </appender>


    <!-- 信息日志类 -->

    <logger name="loginfo">

      <level value="ALL" />

      <appender-ref ref="InfoAppender" />

    </logger>

    <!-- 信息日志附加介质-->

    <appender name="InfoAppender" type="log4net.Appender.RollingFileAppender">

      <!--日志文件路径-->

      <param name="File" value="Log\\LogInfo\\" />

      <!--是否是向文件中追加日志-->

      <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&quot;.htm&quot;" />

      <!--日志根据日期滚动-->

      <param name="RollingStyle" value="Date" />

      <!--信息日志布局-->

      <layout type="log4net.Layout.PatternLayout">

        <param name="ConversionPattern" value="&lt;HR COLOR=blue&gt;%n日志时间:%d [%t] &lt;BR&gt;%n日志级别:%-5p &lt;BR&gt;%n%m &lt;BR&gt;%n &lt;HR Size=1&gt;"  />

      </layout>

    </appender>

  </log4net>


  <!-- To customize the asp.net core module uncomment and edit the following section. 

  For more info see https://go.microsoft.com/fwlink/?linkid=838655 -->

  <!--

  <system.webServer>

    <handlers>

      <remove name="aspNetCore"/>

      <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified"/>

    </handlers>

    <aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" />

  </system.webServer>

  -->


</configuration>

3、在asp.net core项目中 Startup.cs 中需要添加初始化log4net的仓储名,主要是用来给log4net标记一个名称,这边可以随意。

640?wx_fmt=png

 

4、在项目中创建一个类用来记录log的日志格式以及数据分类存放

创建LogHelper.cs,

640?wx_fmt=png

 定义log格式,当然自己可以随意定义哈。

#region 全局异常错误记录持久化

        /// <summary>

        /// 全局异常错误记录持久化

        /// </summary>

        /// <param name="throwMsg"></param>

        /// <param name="ex"></param>

        public static void ErrorLog(string throwMsg, Exception ex)

        {

            string errorMsg = string.Format("【抛出信息】:{0} <br>【异常类型】:{1} <br>【异常信息】:{2} <br>【堆栈调用】:{3}", new object[] { throwMsg,

                ex.GetType().Name, ex.Message, ex.StackTrace });

            errorMsg = errorMsg.Replace("\r\n", "<br>");

            errorMsg = errorMsg.Replace("位置", "<strong style=\"color:red\">位置</strong>");

            logerror.Error(errorMsg);

        }

        #endregion

#region 自定义操作记录

        /// <summary>

        /// 自定义操作记录,与仓储中的增删改的日志是记录同一张表

        /// </summary>

        /// <param name="throwMsg"></param>

        /// <param name="ex"></param>

        public static void WriteLog(string throwMsg, Exception ex)

        {

            string errorMsg = string.Format("【抛出信息】:{0} <br>【异常类型】:{1} <br>【异常信息】:{2} <br>【堆栈调用】:{3}", new object[] { throwMsg,

                ex.GetType().Name, ex.Message, ex.StackTrace });

            errorMsg = errorMsg.Replace("\r\n", "<br>");

            errorMsg = errorMsg.Replace("位置", "<strong style=\"color:red\">位置</strong>");

            logerror.Error(errorMsg);

        }

        #endregion

5、有了以上的log格式,这样我就开始定义一下全局异常处理吧

我这边先创建一个全局异常处理类 GlobalExceptions.cs 然后需要在startup.cs中注入

在ConfigureServices 方法中注入。

//注入全局异常捕获services.AddMvc(o =>{
o.Filters.Add(typeof(GlobalExceptions));
}); 

6、GlobalExceptions类中添加处理,当然异常需要继承IExceptionFilter。

代码如下:

GlobalExceptions 

public class GlobalExceptions : IExceptionFilter

    {

        private readonly IHostingEnvironment _env;

        public GlobalExceptions(IHostingEnvironment env)

        {

            _env = env;

        }

        public void OnException(ExceptionContext context)

        {

            var json = new JsonErrorResponse();

            //这里面是自定义的操作记录日志

            if (context.Exception.GetType() == typeof(UserOperationException))

            {

                json.Message = context.Exception.Message;

                if (_env.IsDevelopment())

                {

                    json.DevelopmentMessage = context.Exception.StackTrace;//堆栈信息

                }

                context.Result = new BadRequestObjectResult(json);//返回异常数据

            }

            else

            {

                json.Message = "发生了未知内部错误";

                if (_env.IsDevelopment())

                {

                    json.DevelopmentMessage = context.Exception.StackTrace;//堆栈信息

                }

                context.Result = new InternalServerErrorObjectResult(json);

            }


            //采用log4net 进行错误日志记录

            LogHelper.ErrorLog(json.Message, context.Exception);


        }

    }

    public class InternalServerErrorObjectResult : ObjectResult

    {

        public InternalServerErrorObjectResult(object value) : base(value)

        {

            StatusCode = StatusCodes.Status500InternalServerError;

        }

    }

JsonErrorResponse.cs 

public class JsonErrorResponse

    {

        /// <summary>

        /// 生产环境的消息

        /// </summary>

        public string Message { get; set; }

        /// <summary>

        /// 开发环境的消息

        /// </summary>

        public string DevelopmentMessage { get; set; }

    }


/// <summary>

    /// 操作日志

    /// </summary>

    public class UserOperationException : Exception

    {

        public UserOperationException() { }

        public UserOperationException(string message) : base(message) { }

        public UserOperationException(string message, Exception innerException) : base(message, innerException) { }

    }

自此,全局异常配置完成,然后我们可以测试一下,随便写一个除以0的代码在日志记录中就会出现如下的展示:

哇,发现我的错误日志的格式非常的清楚,当然这个跟我的做事态度以及性格有很大的关系的啦,毕竟楼主还是很帅的。哈哈哈。

640?wx_fmt=png

 三、NLog使用


 

1、在项目中添加nlog的nuget包引入,“NLog.Web.AspNetCore”

640?wx_fmt=png

2、创建nlog.config文件,大家会发现我的log格式跟上面的格式操作,而且我的分层层次也很清楚。哈哈

<?xml version="1.0" encoding="utf-8" ?>

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"

      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

      autoReload="true">

  <!-- the targets to write to -->

  <targets>

    <!-- 输出到文件,这个文件记录所有的日志 -->

    <target xsi:type="File" name="allfile" fileName="Log\LogAll\${shortdate}.htm"

                layout="&lt;HR COLOR=red&gt;${longdate}&lt;BR&gt;${logger}&lt;BR&gt;${uppercase:${level}}&lt;BR&gt;${message} ${exception}&lt;HR Size=1&gt;" />


    <!-- 输出到文件,这个文件记录错误日志 -->

    <target xsi:type="File" name="logError" fileName="Log\LogError\${shortdate}.htm"

            layout="&lt;HR COLOR=red&gt;【异常时间】:${date} &lt;BR&gt;【异常级别】:${level:uppercase=true} &lt;BR&gt;${message}&lt;HR Size=1&gt;" />


    <!-- 输出到文件,这个文件记录操作日志 -->

    <target xsi:type="File" name="logInfo" fileName="Log\LogInfo\${shortdate}.htm"

                 layout="&lt;HR COLOR=red&gt;【操作时间】:${date} &lt;BR&gt;【操作级别】:${level:uppercase=true} &lt;BR&gt;${message}&lt;HR Size=1&gt;" />

  </targets>

  <!-- rules to map from logger name to target -->

  <rules>

    <!--All logs, including from Microsoft-->

    <logger name="*" minlevel="Trace" writeTo="allfile" />

    <logger name="*" minlevel="Error" writeTo="logError" />

    <logger name="*" minlevel="Info" writeTo="logInfo" />

    <logger name="Microsoft.*" maxLevel="Info" final="true" />

  </rules>

</nlog>

3、在startup.cs中的  Configure方法注入

//ILoggerFactory loggerFactory
loggerFactory.AddNLog(); NLog.LogManager.LoadConfiguration("nlog.config"
); //填入上面创建的文件的名称

 

4、创建NLogHelp.cs类

public class NLogHelp

    {

        public static Logger logger = LogManager.GetCurrentClassLogger();

        public static void ErrorLog(string throwMsg, Exception ex)

        {

            string errorMsg = string.Format("【异常信息】:{0} <br>【异常类型】:{1} <br>【堆栈调用】:{2}",

                new object[] { throwMsg, ex.GetType().Name, ex.StackTrace });

            errorMsg = errorMsg.Replace("\r\n", "<br>");

            errorMsg = errorMsg.Replace("位置", "<strong style=\"color:red\">位置</strong>");

            logger.Error(errorMsg);

        }

        public static void InfoLog(string operateMsg)

        {

            string errorMsg = string.Format("【操作信息】:{0} <br>",

                new object[] { operateMsg });

            errorMsg = errorMsg.Replace("\r\n", "<br>");

            logger.Info(errorMsg);

        }

    }

5、在上面log4net中的GlobalExceptions类把

LogHelper.ErrorLog(json.Message, context.Exception)替换成如下:NLogHelp.ErrorLog(json.Message,context.Exception)即可。

运行测试如下:

【异常时间】:2018/09/03 14:41:36.786 

【异常级别】:ERROR 

【异常信息】:错误消息:Failed to create instance of type

at AspectCore.Injector.ServiceCallSiteResolver.ResolvePropertyInject(ServiceDefinition service)

【异常类型】:InvalidOperationException 

【堆栈调用】: at AspectCore.Injector.ServiceCallSiteResolver.ResolveTypeService(TypeServiceDefinition typeServiceDefinition)

at AspectCore.Injector.ServiceCallSiteResolver.ResolvePropertyInject(ServiceDefinition service)

at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)

at AspectCore.Injector.ServiceResolver.b

自此,完美搞定,等后期我将会介绍采用ELK+NLog进行数据采集及展示,请大家拭目以待吧。

原文链接:https://www.cnblogs.com/guolianyu/p/9580626.html

 
 

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

640?wx_fmt=jpeg

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值