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

  • 相关阅读:
    es手动创建索引,修改索引,删除索引
    es的scoll滚动查询技术
    es倒排索引和正排索引
    linux中按照指定内容查找文件
    es定制排序搜索结果
    es中如何定位不合法搜索
    es中filter和query的对比
    es组合多个条件进行查询
    手动建立mapping以及增加属性
    30分钟学会如何使用Shiro
  • 原文地址:https://www.cnblogs.com/panpanwelcome/p/12916822.html
Copyright © 2011-2022 走看看