總體架構目錄:ASP.NET Core分佈式項目實戰-目錄html
衆所周知,一旦本身的項目報錯,若是沒有進行處理都是顯示不友好的,有得甚至直接爆出錯誤頁面,看的也是很奇怪。web
爲了不出現這樣的錯誤以及在錯誤出現的時候能夠進行收集錯誤,供維護人員進行bug修改,所以須要進行全局異常的收集。json
讓咱們開始部署吧。api
此篇文章的目錄微信
一、log4net使用架構
二、Nlog使用app
後期將會把NLog+ELK進行結合部署收集咱們的asp.net core的項目。你們能夠拭目以待吧。asp.net
而後目前我先引入 log4net nuget包。分佈式
此文件中,我建立了一個是記錄 錯誤的文件夾(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".htm"" /> <!--日誌根據日期滾動--> <param name="RollingStyle" value="Date" /> <!--信息日誌佈局--> <layout type="log4net.Layout.PatternLayout"> <param name="ConversionPattern" value="<HR COLOR=red>%n【異常時間】:%d [%t] <BR>%n【異常級別】:%-5p <BR>%n%m <BR>%n <HR Size=1>" /> </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".htm"" /> <!--日誌根據日期滾動--> <param name="RollingStyle" value="Date" /> <!--信息日誌佈局--> <layout type="log4net.Layout.PatternLayout"> <param name="ConversionPattern" value="<HR COLOR=blue>%n日誌時間:%d [%t] <BR>%n日誌級別:%-5p <BR>%n%m <BR>%n <HR Size=1>" /> </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=".\logs\stdout" /> </system.webServer> --> </configuration>
建立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("\r\n", "<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("\r\n", "<br>"); errorMsg = errorMsg.Replace("位置", "<strong style=\"color:red\">位置</strong>"); logerror.Error(errorMsg); } #endregion
我這邊先建立一個全局異常處理類 GlobalExceptions.cs 而後須要在startup.cs中注入
在ConfigureServices 方法中注入。
//注入全局異常捕獲 services.AddMvc(o => { o.Filters.Add(typeof(GlobalExceptions)); });
代碼以下:
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的nuget包引入,「NLog.Web.AspNetCore」
二、建立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="Log\LogAll\${shortdate}.htm" layout="<HR COLOR=red>${longdate}<BR>${logger}<BR>${uppercase:${level}}<BR>${message} ${exception}<HR Size=1>" /> <!-- 輸出到文件,這個文件記錄錯誤日誌 --> <target xsi:type="File" name="logError" fileName="Log\LogError\${shortdate}.htm" layout="<HR COLOR=red>【異常時間】:${date} <BR>【異常級別】:${level:uppercase=true} <BR>${message}<HR Size=1>" /> <!-- 輸出到文件,這個文件記錄操做日誌 --> <target xsi:type="File" name="logInfo" fileName="Log\LogInfo\${shortdate}.htm" layout="<HR COLOR=red>【操做時間】:${date} <BR>【操做級別】:${level:uppercase=true} <BR>${message}<HR Size=1>" /> </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>
注:而後將此文件點擊右鍵,選擇屬性,把複製輸出目錄修改成「始終複製」,沒法不修改,則會沒法加載此文件。
//ILoggerFactory loggerFactory
loggerFactory.AddNLog();
NLog.LogManager.LoadConfiguration("nlog.config"); //填入上面建立的文件的名稱
而後運行如下便可看到在bin/debug下面生成文件夾
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("\r\n", "<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("\r\n", "<br>"); logger.Info(errorMsg); } }
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進行數據採集及展現,請你們拭目以待吧。
asp.net Core 交流羣:787464275 歡迎加羣交流
若是您認爲這篇文章還不錯或者有所收穫,您能夠點擊右下角的【推薦】按鈕精神支持,由於這種支持是我繼續寫做,分享的最大動力!
微信公衆號:歡迎關注 QQ技術交流羣: 歡迎加羣