1. 程式人生 > >WinForm、ASP.NET、MVC記錄全域性錯誤日誌

WinForm、ASP.NET、MVC記錄全域性錯誤日誌

之前我轉載了一篇“C#使用Log4Net記錄日誌”,但如果是錯誤日誌,則沒必要在每個方法裡面捕獲異常再記錄日誌,這時我們寫一個全域性的錯誤日誌記錄方法就行了,但這全域性到底應該寫在哪呢?

不同的專案寫的地方是不一樣的:WinForm、ASP.NET、MVC

WinForm:在Program.cs檔案裡

        /// <summary>
        /// 應用程式的主入口點。
        /// </summary>
        [STAThread]
        static void Main()
        {
                //處理未捕獲的異常
                Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
                //處理UI執行緒異常
                Application.ThreadException += Application_ThreadException;
                //處理非UI執行緒異常
                AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

                #region 應用程式的主入口點
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
                #endregion
        }

        //處理UI執行緒異常
        static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
        {
            Exception error = e.Exception as Exception;
            //記錄日誌
        }

        //處理非UI執行緒異常
        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            Exception error = e.ExceptionObject as Exception;
            //記錄日誌
        }


ASP.NET:在Global.asax.cs檔案裡

        void Application_Error(object sender, EventArgs e)
        {
            // 在出現未處理的錯誤時執行的程式碼
            Exception error = Server.GetLastError().GetBaseException();
            //記錄日誌
        }


MVC:需要寫一個繼承HandleErrorAttribute的類,然後在檔案FilterConfig.cs裡新增過濾器

    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
            //預設註冊全域性的錯誤處理的過濾器。
            filters.Add(new MyExceptionFilterAttribute());
        }
    }
    /// <summary>
    /// 自定義錯誤處理類
    /// </summary>
    public class MyExceptionFilterAttribute : HandleErrorAttribute
    {
        public override void OnException(ExceptionContext filterContext)
        {
            base.OnException(filterContext);
            //處理錯誤訊息
            Exception error = filterContext.Exception;
            //記錄日誌         
        }
    }

最後,我們就可以自己寫一個方法,用Log4Net元件記錄錯誤日誌。

由於採用全域性記錄日誌,一般我們只建立一個log4net.ILog例項,因此在記錄日誌過於頻繁的時候,應該要考慮例項被其它執行緒佔用時無法記錄的問題。解決方法如下:

1、單執行緒中用鎖。這種方法容易造成鎖等待從而造成資源浪費。

2、在每個配置檔案每個appender節點裡面新增

      <!--記錄日誌寫入檔案時,不鎖定文字檔案,防止多執行緒時不能寫Log,官方說執行緒非安全-->

      <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
3、把多執行緒轉為單執行緒:採用資料庫佇列。先把日誌記錄進資料庫佇列,再每隔一段時間把佇列的資訊記錄成檔案,記錄後清空佇列