net core体系-web应用程序-4asp.net core2.0 项目实战(1)-11项目日志解决方案
本文目錄
1. Net下日志記錄
2. NLog的使用
??? 2.1 添加nuget引用NLog.Web.AspNetCore
??? 2.2 配置文件設(shè)置
??? 2.3 依賴配置及調(diào)用
??? 2.4 日志類型介紹
??? 2.5 產(chǎn)生的日志文件
3. 基于Microsoft.Extensions.Logging封裝
??? 3.1 添加引用Microsoft.Extensions.Logging
??? 3.2 實(shí)現(xiàn)我們的Logger
??? 3.3 調(diào)用WLogger
2018-03-28 補(bǔ)充
4. 總結(jié)
1.? Net下日志記錄
Net Freamwork框架下在日志記錄框架有很多,常見的有NLog、Log4Net、Loggr和內(nèi)置 Microsoft.Diagnostics.Trace/Debug/TraceSource等。Asp.Net Core 2.0下大部分框架已不支持,Microsoft提供Microsoft.Extensions.Logging供大家實(shí)現(xiàn)自己的記錄日志框架。現(xiàn)在筆者了解到的NLog已支持Net Core,下面我們介紹下nlog在項(xiàng)目中的使用以及基于Microsoft.Extensions.Logging封裝自己的日志記錄類。
1.? NLog的使用
2.1添加nuget引用NLog.Web.AspNetCore
2.2配置文件設(shè)置
在Asp.Net Core 2.0項(xiàng)目實(shí)戰(zhàn)項(xiàng)目中,我們把配置文件統(tǒng)一放在configs文件夾中,方便管理。讀取時(shí)用Path.Combine("configs", "nlog.config")即可。下面是nlog.config的配置。
<?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"internalLogLevel="Warn"internalLogFile="internal-nlog.txt"><!--define various log targets--><targets><!--write logs to file--><target xsi:type="File" name="allfile" fileName="nlog-all-${shortdate}.log"layout="${longdate}|${logger}|${uppercase:${level}}|${message} ${exception}" /><target xsi:type="File" name="ownFile-web" fileName="nlog-my-${shortdate}.log"layout="${longdate}|${logger}|${uppercase:${level}}|${message} ${exception}" /><target xsi:type="Null" name="blackhole" /></targets><rules><!--All logs, including from Microsoft--><logger name="*" minlevel="Trace" writeTo="allfile" /><!--Skip Microsoft logs and so log only own logs--><logger name="Microsoft.*" minlevel="Trace" writeTo="blackhole" final="true" /><logger name="*" minlevel="Trace" writeTo="ownFile-web" /></rules></nlog>2.3依賴配置及調(diào)用
在startup.cs中配置日志工廠,添加使用的服務(wù)配置后在項(xiàng)目中就可以調(diào)用。
?
/// <summary>/// 配置/// </summary>/// <param name="app"></param>/// <param name="env"></param>/// <param name="loggerFactory"></param>public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory){loggerFactory.AddNLog();//添加NLog //讀取Nlog配置文件,這里如果是小寫,文件也一定是小寫,否則linux下不識別 env.ConfigureNLog(Path.Combine("configs", "nlog.config"));}?
? nlog調(diào)用,如在Controller中調(diào)用,如:在HomeController中
2.4 日志類型介紹
public enum LogLevel {Debug = 1,Verbose = 2,Information = 3,Warning = 4,Error = 5,Critical = 6,None = int.MaxValue }2.5產(chǎn)生的日志文件
日志的位置默認(rèn)是在bin\Debug\netcoreapp2.0下面
?
日志文件內(nèi)容根據(jù)文件名可以很方便的區(qū)分開,其中nlog-all包含的內(nèi)比較多,nlog-my中就只包含了我們記錄日志的內(nèi)容,大家動(dòng)手試一下。
?
3.基于Microsoft.Extensions.Logging封裝
由于受老項(xiàng)目webform影響,記錄日志是在第三方類庫dll中封裝好了幫助類,這樣在可以在項(xiàng)目中任何位置方便調(diào)用,這里我的nc.common工具庫WLogger基于Microsoft NET Core的日志模型主要由三個(gè)核心對象構(gòu)成,它們分別是Logger、LoggerProvider和LoggerFactory。現(xiàn)在只實(shí)現(xiàn)了文件記錄日志txt,數(shù)據(jù)庫模式有業(yè)務(wù)需求的朋友可自己擴(kuò)展。
?
3.1添加引用Microsoft.Extensions.Logging
擴(kuò)展微軟日志記錄框架,集成一個(gè)自己的Logger,現(xiàn)在擴(kuò)展的是txt形式,后續(xù)可參考完善數(shù)據(jù)庫模式。添加引用dll后,增加配置文件并配置,這里我先加在appsettings.json文件中,主要是配置是否開啟日志和日志記錄。
?
?
3.2 實(shí)現(xiàn)我們的Logger
首先實(shí)現(xiàn)日志工廠的擴(kuò)展LoggerFactoryExtensions,為net core 依賴注入LoggerFactory擴(kuò)張一個(gè)方法,提供增加日志寫文件方式的入口。
using Microsoft.Extensions.Logging;namespace NC.Common {public static class LoggerFactoryExtensions{public static ILoggerFactory AddFileLogger(this ILoggerFactory factory){factory.AddProvider(new FileLoggerProvider());return factory;}} }然后實(shí)現(xiàn)ILoggerProvider接口,FileLoggerProvider提供程序真正具有日志寫入功能的Logger。
using Microsoft.Extensions.Logging;namespace NC.Common {public class FileLoggerProvider : ILoggerProvider{/// <summary>/// 默認(rèn)構(gòu)造函數(shù),根據(jù)Provider進(jìn)此構(gòu)造函數(shù)/// </summary>/// <param name="categoryName"></param>/// <returns></returns>public ILogger CreateLogger(string categoryName){return new FileLogger(categoryName);}public void Dispose(){}} }最后實(shí)現(xiàn)ILogger接口FileLogger繼承并進(jìn)行封裝,方便寫入文本日志。
using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.IO; using System.Text;namespace NC.Common {public class FileLogger : ILogger{private string name;private bool IsOpen;private string WPath;public FileLogger(string _name){name = _name;}public IDisposable BeginScope<TState>(TState state){return null;}/// <summary>/// 是否禁用/// </summary>/// <param name="logLevel"></param>/// <returns></returns>public bool IsEnabled(LogLevel logLevel){return true;}/// <summary>/// 實(shí)現(xiàn)接口ILogger/// </summary>/// <typeparam name="TState"></typeparam>/// <param name="logLevel"></param>/// <param name="eventId"></param>/// <param name="state"></param>/// <param name="exception"></param>/// <param name="formatter"></param>public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter){IsOpen = UtilConf.GetSection("WLogger")["IsOpen"] == "true" ? true : false;if (IsOpen){//獲取日志信息var message = formatter?.Invoke(state, exception);//日志寫入文件LogToFile(logLevel, message);}}/// <summary>/// 記錄日志/// </summary>/// <param name="level">等級</param>/// <param name="message">日志內(nèi)容</param>private void LogToFile(LogLevel level, string message){var filename = GetFilename();var logContent = GetLogContent(level, message);File.AppendAllLines(filename, new List<string> { logContent }, Encoding.UTF8);}/// <summary>/// 獲取日志內(nèi)容/// </summary>/// <param name="level">等級</param>/// <param name="message">日志內(nèi)容</param>/// <returns></returns>private string GetLogContent(LogLevel level, string message){return $"[{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.h3")}]{level}|{name}|{message}";}private string DirectorySeparatorChar = Path.DirectorySeparatorChar.ToString();//目錄分隔符/// <summary>/// 獲取文件名/// </summary>private string GetFilename(){var dir = "";WPath = UtilConf.GetSection("WLogger")["WPath"];if (WPath.IndexOf(":") > -1){dir = WPath;}else{//此方法不是真正的獲取應(yīng)用程序的當(dāng)前方法,而是執(zhí)行dotnet命令所在目錄dir = Directory.GetCurrentDirectory() + WPath;}if (!Directory.Exists(dir))Directory.CreateDirectory(dir);var result = $"{dir}/WLog-{DateTime.Now.ToString("yyyy-MM-dd")}.txt".Replace("/",DirectorySeparatorChar);return result;}} }3.3 調(diào)用WLogger
在nc.common類庫中封裝好logger實(shí)現(xiàn)后,在調(diào)用連接使用數(shù)據(jù)庫在core類庫中調(diào)用實(shí)例如下。
首先我們先做一下封裝調(diào)用類
?
using Microsoft.Extensions.Logging;namespace NC.Common {public class UtilLogger<T>{private static ILogger iLog;public static ILogger Log{get{if (iLog != null) return iLog;第一種寫法//ILoggerFactory loggerFactory = new LoggerFactory();//loggerFactory.AddFileLogger();//iLog = loggerFactory.CreateLogger<DbCommand>();//第二種寫法iLog = new LoggerFactory().AddFileLogger().CreateLogger<T>();return iLog;}set => iLog = value;}} }然后在DbCommand中調(diào)用就可以直接寫成:
public static ILogger Log = UtilLogger<DbCommand>.Log;//日志記錄
Log. LogInformation(string);
Log.LogError(string)
詳細(xì)方法還可以參考
?
2018-03-28補(bǔ)充:
日志記錄與全局錯(cuò)誤處理結(jié)合,首先創(chuàng)建全局錯(cuò)誤過濾類HttpGlobalExceptionFilter并在startup.cs中ConfigureServices方法下添加
services.AddMvc(options =>{options.Filters.Add(typeof(HttpGlobalExceptionFilter));//全局錯(cuò)誤過濾日志}).AddControllersAsServices();然后實(shí)現(xiàn)OnException方法并記錄日志,這樣系統(tǒng)只要報(bào)異常,日志 就會(huì)被記錄下來。
using System; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Logging; using NC.Common;namespace NC.MVC {/// <summary>/// 錯(cuò)誤處理類/// </summary>public class HttpGlobalExceptionFilter : IExceptionFilter{private readonly IHostingEnvironment _env;public static ILogger Log = UtilLogger<HttpGlobalExceptionFilter>.Log;//日志記錄public HttpGlobalExceptionFilter(IHostingEnvironment env){this._env = env;}public ContentResult FailedMsg(string msg = null){string retResult = "{\"status\":" + JHEnums.ResultStatus.Failed + ",\"msg\":\"" + msg + "\"}";//, msg);string json = JsonHelper.ObjectToJSON(retResult);return new ContentResult() { Content = json };}public void OnException(ExceptionContext filterContext){if (filterContext.ExceptionHandled)return;//執(zhí)行過程出現(xiàn)未處理異常Exception ex = filterContext.Exception; #if DEBUGif (filterContext.HttpContext.Request.IsAjaxRequest()){string msg = null;if (ex is Exception){msg = ex.Message;filterContext.Result = this.FailedMsg(msg);filterContext.ExceptionHandled = true;return;}}this.LogException(filterContext);return; #endifif (filterContext.HttpContext.Request.IsAjaxRequest()){string msg = null;if (ex is Exception){msg = ex.Message;}else{this.LogException(filterContext);msg = "服務(wù)器錯(cuò)誤";}filterContext.Result = this.FailedMsg(msg);filterContext.ExceptionHandled = true;return;}else{//對于非 ajax 請求this.LogException(filterContext);return;}}/// <summary>/// 記錄日志/// </summary>/// <param name="filterContext"></param>private void LogException(ExceptionContext filterContext){string mid = filterContext.HttpContext.Request.Query["mid"];//codding 后續(xù)完善每個(gè)action帶一個(gè)idvar areaName = (filterContext.RouteData.DataTokens["area"] == null ? "" : filterContext.RouteData.DataTokens["area"]).ToString().ToLower();var controllerName = (filterContext.RouteData.Values["controller"]).ToString().ToLower();var actionName = (filterContext.RouteData.Values["action"]).ToString().ToLower();#region --記錄日志 codding 后續(xù)增加自定義字段的日志。如:記錄Controller/action,模塊ID等--Log.LogError(filterContext.Exception, "全局錯(cuò)誤:areaName:" + areaName + ",controllerName:" + controllerName + ",action:" + actionName);#endregion}} }?
?
4.總結(jié)
不管是生產(chǎn)環(huán)境還是開發(fā)環(huán)境,總會(huì)碰到這樣或那樣的問題,這時(shí)日志記錄就為我們提供了記錄分析問題的便利性,net core 2.0下記錄日志功能是最需要我們及時(shí)實(shí)現(xiàn)的功能,這樣為我們接下來的學(xué)習(xí)提供技術(shù)支撐。另外net core 生態(tài)還不完善,很多功能需要我們自己動(dòng)手去實(shí)現(xiàn),在這里希望大家多動(dòng)手去實(shí)現(xiàn)去分享,文中有不清楚或有問題歡迎留言討論。
參考:
https://msdn.microsoft.com/magazine/mt694089
https://www.cnblogs.com/artech/p/inside-net-core-logging-2.html
https://www.cnblogs.com/calvinK/p/5673218.html
轉(zhuǎn)載于:https://www.cnblogs.com/hmit/p/10769576.html
總結(jié)
以上是生活随笔為你收集整理的net core体系-web应用程序-4asp.net core2.0 项目实战(1)-11项目日志解决方案的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 流畅的python不适合初学者_学习《流
- 下一篇: C11 多线程初学1