.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("\r\n");
            strInfo.Append("1. 操作時間: " + logMessage.OperationTime + " \r\n");
            strInfo.Append("2. 操作人: " + logMessage.OperationName + " \r\n");
            strInfo.Append("3. Ip  : " + logMessage.IpAddress + "\r\n");
            strInfo.Append("4. 錯誤內容: " + logMessage.LogInfo + "\r\n");
            strInfo.Append("5. 跟蹤: " + logMessage.StackTrace + "\r\n");
            strInfo.Append("----------------------------------------------------------------END---------------------------------------------------------------\r\n");
            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類中!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM