• .NET Core中使用NLog之封装、过滤器、注入全局使用


    上篇咋们聊到NLog在Core中比较基础的使用,这篇接着上篇,对NLog做下封装和过滤器集成,然后全局使用

    说道这里咋们想说说过滤器Filter,Filter其实是延续ASP.NET MVC的产物,同样保留了五种的Filter,分别是Authorization Filter、Resource Filter、Action Filter、Exception Filter及Result Filter。

    本篇咋们就用NLog日志记录结合Filter中的Exception Filter异常日志全局过滤器,记录全局异常日志方便咋们排错,进入主题:

    1、首先咋们创建个单独的项目,命名为Nlog.Framework,然后在类库中添加一个Log文件夹,把所有Log相关的文件都放到该文件夹下,添加后的项目结构如下图所示:

    2、在Log文件下创建个LogMessage类,里面是要记录的一些信息属性字段,代码如下:

    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace Nlog.Framework.Log
    {
        /// <summary>
        /// 日志消息
        /// </summary>
        public class LogMessage
        {
            /// <summary>
            /// IP
            /// </summary>
            public string IpAddress { get; set; }
    
            /// <summary>
            /// 操作人
            /// </summary>
            public string OperationName { get; set; }
    
            /// <summary>
            /// 操作时间
            /// </summary>
            public DateTime OperationTime { get; set; }
    
            /// <summary>
            /// 日志信息
            /// </summary>
            public string LogInfo { get; set; }
    
            /// <summary>
            /// 跟踪信息
            /// </summary>
            public string StackTrace { get; set; }
        }
    }
    View Code

    3、在Log文件下创建个格式化LogFormat类,用来格式化日志输出内容(日志看起来没那么凌乱),代码如下:

    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace Nlog.Framework.Log
    {
        public class LogFormat
        {
            public static string ErrorFormat(LogMessage logMessage)
            {
                StringBuilder strInfo = new StringBuilder();
                strInfo.Append("
    ");
                strInfo.Append("1. 操作时间: " + logMessage.OperationTime + " 
    ");
                strInfo.Append("2. 操作人: " + logMessage.OperationName + " 
    ");
                strInfo.Append("3. Ip  : " + logMessage.IpAddress + "
    ");
                strInfo.Append("4. 错误内容: " + logMessage.LogInfo + "
    ");
                strInfo.Append("5. 跟踪: " + logMessage.StackTrace + "
    ");
                strInfo.Append("----------------------------------------------------------------END---------------------------------------------------------------
    ");
                return strInfo.ToString();
            }
        }
    }
    View Code

    4、在Log文件下定义一个接口,代码如下:

    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace Nlog.Framework.Log
    {
        public interface INLogHelper
        {
            void LogError(Exception ex);
        }
    }
    View Code

    5、在Log文件下定义接口的实现类,代码如下:

    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.Logging;
    using System;
    
    namespace Nlog.Framework.Log
    {
        public class NLogHelper : INLogHelper
        {
            private readonly IHttpContextAccessor _httpContextAccessor;
            private readonly ILogger<NLogHelper> _logger;
            public NLogHelper(IHttpContextAccessor httpContextAccessor, ILogger<NLogHelper> logger)
            {
                _httpContextAccessor = httpContextAccessor;
                _logger = logger;
            }
    
            public void LogError(Exception ex)
            {
                LogMessage logMessage = new LogMessage();
                logMessage.IpAddress = _httpContextAccessor.HttpContext.Request.Host.Host;
                if (ex.InnerException != null)
                    logMessage.LogInfo = ex.InnerException.Message;
                else
                    logMessage.LogInfo = ex.Message;
                logMessage.StackTrace = ex.StackTrace;
                logMessage.OperationTime = DateTime.Now;
                logMessage.OperationName = "administator";
                _logger.LogError(LogFormat.ErrorFormat(logMessage));
    
            }
        }
    }
    View Code

    6、添加个Filter文件夹,在当前文件夹下创建个全局异常过滤器,代码如下:

    using Microsoft.AspNetCore.Mvc.Filters;
    using Nlog.Framework.Log;
    using System;
    using System.Threading.Tasks;
    
    namespace FristCoreProgram.Filter
    {
        public class CustomerGlobalExceptionFilterAsync : ActionFilterAttribute, IAsyncExceptionFilter
        {
            private readonly INLogHelper _logHelper;
            public CustomerGlobalExceptionFilterAsync(INLogHelper logHelper)
            {
                _logHelper = logHelper;
            }
    
    
            /// <summary>
            /// 重新OnExceptionAsync方法
            /// </summary>
            /// <param name="context">异常信息</param>
            /// <returns></returns>
            public Task OnExceptionAsync(ExceptionContext context)
            {
                // 如果异常没有被处理,则进行处理
                if (!context.ExceptionHandled)
                {
                    // 记录错误信息
                    _logHelper.LogError(context.Exception);
                    // 设置为true,表示异常已经被处理了,其它捕获异常的地方就不会再处理了
                    context.ExceptionHandled = true;
                }
                return Task.CompletedTask;
            }
        }
    }
    View Code

    7、修改Program类文件,代码如下:

    public static void Main(string[] args)
            {
                //设置读取指定位置的nlog.config文件
                //NLogBuilder.ConfigureNLog("XmlConfig/nlog.config");
                //CreateWebHostBuilder(args).Build().Run();
    
    
                //读取指定位置的NLog配置文件
                var logger = NLogBuilder.ConfigureNLog("XmlConfig/nlog.config").GetCurrentClassLogger();
                try
                {
                    logger.Info("Init Main...");
                    CreateWebHostBuilder(args).Build().Run();
                }
                catch (System.Exception ex)
                {
                    logger.Error(ex, "Stopped program because of exception");
                }
                finally
                {
                    LogManager.Shutdown();
                }
            }
    
            public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
                WebHost.CreateDefaultBuilder(args)
                    .UseStartup<Startup>()
                    //配置使用Nlog
                    .UseNLog();
    View Code

    8、在Startup类里面ConfigureServices注入全局异常过滤器,,代码如下:

    public void ConfigureServices(IServiceCollection services)
            {
                services.Configure<CookiePolicyOptions>(options =>
                {
                    // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                    options.CheckConsentNeeded = context => true;
                    options.MinimumSameSitePolicy = SameSiteMode.None;
                });
    
    
                services.AddMvc(options => {
                    #region NLog过滤器注册
                    options.Filters.Add(typeof(CustomerGlobalExceptionFilterAsync));
                    #endregion
                }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    
              
                services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
                services.AddSingleton<INLogHelper, NLogHelper>();
    
                //services.AddControllers();
    
            }
    View Code

    PS:需要注意的是,由于Core的版本不同,Startup注入过滤器时方式有所不同

    本例是core2.2版本注入的方式是:

        options.Filters.Add(typeof(CustomerGlobalExceptionFilterAsync));

    而core3.1版本注入的方式是:

        services.AddControllers(options => options.Filters.Add(typeof(CustomerGlobalExceptionFilterAsync)));

    9、最后再controller模拟个异常测试过滤器,代码如下:

    最最最后,访问模拟异常的Action,查看日志文件,如下:

     以上完成,这里只是封装了Error,如果是其他级别的日志,可以自己封装,然后注入到Startup类中!

  • 相关阅读:
    Python
    QinQ 技术解析
    TLS/SSL 协议
    TLS/SSL 协议
    TLS/SSL 协议
    排序算法之基本排序算法(冒泡、插入、选择)
    Spring Boot 学习笔记--手写版
    mysql -- collection一对多查询
    mybatis 批量操作增删改查
    easyUI之datagrid绑定后端返回数据的两种方式
  • 原文地址:https://www.cnblogs.com/become/p/15065997.html
Copyright © 2020-2023  润新知