天天看點

【UWP】在 UWP 中使用 Exceptionless 進行遙測

2020年4月10日更新:

官方 nuget 新版本已釋出

https://www.nuget.org/packages/Exceptionless

2020年1月17日更新:

nightly build 版本已釋出

https://www.myget.org/feed/exceptionless/package/nuget/Exceptionless

2020年1月16日更新:

PR 已合并了,等待官方釋出新的 nuget 包

2020年1月10日更新:

clone 官方源碼調了一下找到問題所在了,UWP 的 release 模式下, Assembly.GetCallingAssembly() 不可用導緻,已給 Exceptionless 發 PR 了。

https://github.com/exceptionless/Exceptionless.Net/pull/219

2020年1月9日更新:

目前 Exceptionless 存在 bug,導緻在 UWP 的 release 模式下不可用,已給官方提 bug

https://github.com/exceptionless/Exceptionless.Net/issues/218

各位看官暫時不用往下看了。

前幾個星期在公司的測試伺服器上搭建了 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 事件來捕獲的。這裡我們看第二行的實作:

【UWP】在 UWP 中使用 Exceptionless 進行遙測

可見是對 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 平台。

【UWP】在 UWP 中使用 Exceptionless 進行遙測

完美!