前幾個星期在公司的測試伺服器上搭建了 Exceptionless 對公司的 Asp.net core 項目進行遙測。在之前都是遠程桌面登錄上去,然後去翻日誌文件看有沒有異常,效率極其的低。用了 Exceptionless 之後,效率高了不少,而且能收集到更多信息了。 最近準備要過年了,項目也上線了一 ...
前幾個星期在公司的測試伺服器上搭建了 Exceptionless 對公司的 Asp.net core 項目進行遙測。在之前都是遠程桌面登錄上去,然後去翻日誌文件看有沒有異常,效率極其的低。用了 Exceptionless 之後,效率高了不少,而且能收集到更多信息了。
最近準備要過年了,項目也上線了一段時間趨於穩定,算是比較閑了一點。想著要不把手上的 UWP 項目也加上 Exceptionless 進行遙測吧,畢竟微軟商店的 Dashboard 那異常也幾乎是看不出啥的,而且這測試伺服器性能又是過剩的,不用白不用。
但我一操作起來,就發現了個大問題,Exceptionless 官方並沒有提供 UWP 的庫(Winform、WPF、asp.net core 的都有)。翻查了 github 上相關的 issue,官方建議是用 .net standard 版本的。然而實際操作之後,我發現還需要額外的代碼來處理 UWP 中的 UnhandledException,本文就記錄一下。
首先當然是在 Exceptionless 平臺上創建項目獲取 ApiKey 了,這個就不多說了。然後 UWP 項目引用 Exceptionless 的 nuget 包。
在 App.xaml.cs 的構造函數中添加 SetUpExceptionless 代碼:
public App() { this.InitializeComponent(); this.Suspending += OnSuspending; SetUpExceptionless(); }
然後先初步實現 SetUpExceptionless 方法:
private void SetUpExceptionless() { var client = ExceptionlessClient.Default; client.Configuration.ServerUrl = ""; client.Configuration.ApiKey = ""; client.Startup(); }
由於是自建 Exceptionless 平臺,所以需要配置一下 ServerUrl。ApiKey 配置為從平臺獲取到的 ApiKey。
接下來是處理 UnhandledException,在 UWP 平臺中,有兩種情況,一種是在 App 類上觸發的,另一種是在 AppDomain 上觸發的。這兩種我們都要監聽到。但如何監聽呢,這裡先看看官方在 WPF 平臺是如何實現的:
主要是圖上紅框的兩行,第一行主要是捕獲線程的異常,第二行捕獲了 App 的異常。而捕獲線程異常的方法內部用到了 Winform 的類,這裡我們就忽略,因為 UWP 里沒有這些類,而且 UWP 中非 UI 線程的異常是可以通過 AppDomain.UnhandledException 事件來捕獲的。這裡我們看第二行的實現:
可見是對 System.Windows.Application.Current.DispatcherUnhandledException 事件進行了訂閱,然後給 Exceptionless。
依樣畫葫蘆,完善我們的 SetUpExceptionless 方法:
private void SetUpExceptionless() { var client = ExceptionlessClient.Default; client.Configuration.ServerUrl = ""; client.Configuration.ApiKey = ""; UnhandledException += (sender, args) => { var contextData = new ContextData(); contextData.MarkAsUnhandledError(); contextData.SetSubmissionMethod("App_UnhandledException"); args.Exception.ToExceptionless(contextData, ExceptionlessClient.Default).Submit(); client.ProcessQueue(); }; AppDomain.CurrentDomain.UnhandledException += (sender, args) => { var exception = args.ExceptionObject as Exception; if (exception == null) { return; } var contextData = new ContextData(); contextData.MarkAsUnhandledError(); contextData.SetSubmissionMethod("AppDomain_UnhandledException"); exception.ToExceptionless(contextData, ExceptionlessClient.Default).Submit(); client.ProcessQueue(); }; client.Startup(); }
接下來我們測試一下是否起效,先手動拋個異常,我就直接建一個 Button,然後 Click 拋個異常好了。
private void TestButton_Click(object sender, RoutedEventArgs e) { throw new Exception("測試 Exceptionless 集成"); }
運行後,點擊按鈕,然後 App 炸掉之後我們去看 Exceptionless 平臺。
完美!