zoukankan      html  css  js  c++  java
  • asp.net core添加全局异常处理及log4net、Nlog应用(转发)

    https://www.cnblogs.com/guolianyu/p/9580626.html?spm=a2c6h.12873639.0.0.5b8968cduViP7W

    0、目录


     整体架构目录:ASP.NET Core分布式项目实战-目录

    一、介绍


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

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

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

     让我们开始部署吧。

    此篇文章的目录

    1、log4net使用

    2、Nlog使用

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

    二、部署(log4net使用)


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

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

    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=".logsstdout" />
      </system.webServer>
      -->
    
    </configuration>
    复制代码

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

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

    创建LogHelper.cs,

    定义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("
    ", "<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("
    ", "<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; }
        }
    复制代码

    UserOperationException.cs

    复制代码
    /// <summary>
        /// 操作日志
        /// </summary>
        public class UserOperationException : Exception
        {
            public UserOperationException() { }
            public UserOperationException(string message) : base(message) { }
            public UserOperationException(string message, Exception innerException) : base(message, innerException) { }
        }
    复制代码

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

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

    三、NLog使用


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

    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="LogLogAll${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="LogLogError${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="LogLogInfo${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"); //填入上面创建的文件的名称

     然后运行以下即可看到在bin/debug下面生成文件夹

    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("
    ", "<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("
    ", "<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进行数据采集及展示,请大家拭目以待吧。

  • 相关阅读:
    linux之awk命令
    HDU 2097 Sky数 进制转换
    HDU 2077 汉诺塔IV
    HDU 2094 产生冠军 dfs加map容器
    HDU 2073 叠框
    HDU 2083 简易版之最短距离
    HDU 2063 过山车 二分匹配
    天梯 1014 装箱问题
    天梯 1214 线段覆盖
    天梯 1098 均分纸牌
  • 原文地址:https://www.cnblogs.com/panpanwelcome/p/12916822.html
Copyright © 2011-2022 走看看