2016/7/11

學習 Application Insights 協助記錄 Apps 的相關動作

學習 Application Insights 協助記錄 Apps 的相關動作

過去常聽到 Google GA 可以讓 Android 與 iOS Apps 開發商可以記錄與分析使用者在 Apps 操作的習慣,
停留在那些功能或是畫面上的時間與功能使用率。雖然 Google GA 沒有支持 Windows Phone / Windows Store Apps 但在 Codeplex 仍可以找到第三方開發的元件:Google Analytics SDK for Windows 8 and Windows Phone

不過 Microsoft 在 Azure 上提供了新的元素:Application Insights,協助開發商可以做到分析應用程式的功能。
image

根據官方說明的重點如下:
Application Insights 目前為預覽階段。
Application Insights 可讓您監視即時應用程式在以下各方面的情況:
  • 可用性 - 我們會每隔幾分鐘從世界各地測試一下 URL。
  • 效能 - 偵測及診斷效能問題和例外狀況。
  • 流量 - 了解哪些使用者將應用程式運用在哪些用途,以利改善應用程式。
  • 支源項目 - ASP.NET、Java Web applications、WCF Services、Windows Phone 與 Windows Store apps。
本身主要屬於 Azure 上的一個服務,與原本 Apps 而言是屬於額外的元件,所以需要在專案裡加上一些 SDKs 與 Templates 的引入。

接下來參考<Application Insights: Get started with Windows device apps>的內容加以說明。

目前支持 for Phone/Store Apps 觀查二個重點:
  • Usage - Learn how many users you have and what they are doing with your app.
          從中就可以得知用戶習慣停留在那一個畫面與目前有多少用戶在操作那些畫面與功能。

  • Crashes - Get diagnostic reports of crashes and understand their impact on users.
          Crashes 回報的內容也相對於 Dev Center 提供前 30 天 Crashes reports 來的有用許多。

這二個重點可藉由在 App 加入數種觀測點來協助:
  • TrackEvent
  • TrackPage
  • TrackTrace
  • TrackMetric
  • TrackRequest
  • TrackException

例如:
Open diagnostic search

詳細如何加自己的專案或是建立專案並加入 Application insights 請參考<Application Insights: Get started with Windows device apps>的說明。

重點:
a. 新建立的專案在方案建立視窗時要加入 Application insights 的選項;
b. 如果是已存在的專案要加入 Application insights,先藉由 NuGet 安裝必要的 application insights;
     (由 MS 官方輸出版本:Application Insights Telemetry SDK For Windows Store Apps 與 Application Insights Telemetry SDK for Multi-device hybrid Apps)
c. 藉由在專案按下右鍵,選擇「Open Application Insights」,即可以進入 Application Insights 在 Azure Portal 的畫面;
d. 可搭配 Visual Studio 進行 Debugs 的測試。
如果你也是 Unverisal App 的專案在安裝上遇到問題可以參考文章後半段的說明。


根據<自訂事件和度量的 Application Insights API>的介紹往下說明 Application Insights 如何定義每一次的 session 為何與相關的重點:

[注意事項]
1. 每一個應用程式都有一些度量和事件的數目限制
2. 每個檢測金鑰 (也就是每個應用程式) 每秒最多 500 個遙測資料點 (SDK 模組傳送的標準遙測、傳送的自訂事件、度量和其他遙測)。
3. 應用程式具有最多 200 個唯一度量名稱和 200 個唯一屬性名稱
    度量包括透過 TrackMetric 傳送的資料,以及其他資料類型上的測量,例如事件。每個檢測金鑰的度量和屬性名稱是全域的,不只限於資料類型。
4. 只有在每個屬性具有少於 100 個唯一值時,屬性才能用於篩選和分組依據
     唯一值超過 100 之後,屬性仍可用於搜尋與篩選,但無法用於篩選器
5.  標準屬性,例如要求名稱和網頁 URL 會限制為每週 1000 個唯一值。
     超過 1000 個唯一值之後,額外值都會標示為「其他值」。原始值仍然可以用於全文檢索搜尋和篩選。
6. 資料保留多久?請參閱資料保留和隱私權
7. ApplicationInsights.config 可加入初始化或管理 telemetryClient ,可參考<使用 ApplicationInsights.config 或 .xml 設定 Application Insights SDK>。


上述了解了如何將 Apps 專案加入 Application Insights 後,接著往下了解怎麼依需求加入觀查點與相關 methods 的使用。

Custom events and metrics with the Application Insights API
     參考該篇了解如何在 App 增加自訂義的 Event、PageView、Metric、Exception、Request 與 Trace,往下針對這幾點加以說明:

METHOD USED FOR
TrackPageView Pages, screens, blades or forms
TrackEvent User actions and other events. Used to track user behavior or to monitor performance.
TrackMetric Performance measurements such as queue lengths not related to specific events.
TrackException Log exceptions for diagnosis. Trace where they occur in relation to other events and examine stack traces.
TrackRequest Log the frequency and duration of server requests for performance analysis.
TrackTrace Diagnostic log messages. You can also capture 3rd-party logs.

要操作上述這些 Method 之前要先建立 TelemetryClient,並且設定它基礎的參數,如下:
/// <summary>
/// Allows tracking page views, exceptions and other telemetry through the Microsoft Application Insights service.
/// </summary>
public static TelemetryClient TelemetryClient;
public App()
{
   // 初始化 TelemetryClient  元件
   TelemetryClient = new TelemetryClient();
   // 可指定是否為 DeveloperMode  模式,預設 false,true 的話可以在 dashboard 更快收到訊息
   TelemetryConfiguration.Active.TelemetryChannel.DeveloperMode = true;
TelemetryClient.InstrumentationKey = "";

initialAppTheme();

   this.InitializeComponent();
   this.Suspending += this.OnSuspending;
   this.Resuming += App_Resuming;
 

#if DEBUG
System.Threading.Tasks.TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
#endif


DebugSettings.BindingFailed += (sender, args) =>
{
    };

UnhandledException += (sender, e) =>{      }; 

}


a. TelemetryContext
     Application insights 負責收集所有事件、相關資訊的元件。它搭配 ApplicationInsights.config  初始化它的資料與模組,也可藉由程式碼加以調整。
主要的屬性如下:
Name Description
Component ComponentContext 類別。負責描述 Microsoft.ApplicationInsights.DataContracts.TelemetryContext。Identifies the app and its version。
Device DeviceContext 類別。描述執行該元件的設備資訊。包括:Language、Id、OemName、OperatingSystem、ScreenResolution、Model、RoleInstance、NetworkType…等。Data about the device on which the app is running (in web apps, this is the server or client device from which the telemetry is sent)
InstrumentationKey 代表 Application insights 的識別值。Identifies the Application Insights resource in Azure where the telemetry will appear. Usually picked up from ApplicationInsights.config
Operation OperationContext 類別,Encapsulates information about an operation. Operation normally reflects an end to end scenario that starts from a user action (e.g. button click).
  • Id: A generated value that correlates different events, so that when you inspect any event in Diagnostic Search, you can find "Related items"
  • Name: The URL of the HTTP request
  • SyntheticSource: If not null or empty, this string indicates that the source of the request has been identified as a robot or web test. By default it will be excluded from calculations in Metrics Explorer.
Properties IDictionary<string, string>,該元件的特定屬性 application-defined property values。

該屬性的設定值在每一個 Track 都會被加入,類似預設屬性。例如:設定 version… 等。

Properties that are sent with all telemetry data. Can be overridden in individual Track* calls.
Session SessionContext 類別,描述此次 Session tracked 的資訊。

Identifies the user's session. The Id is set to a generated value, which is changed when the user has not been active for a while.

其屬性有:application-defined session ID,代表 session 的識別值。
  • A session is counted when the app is suspended (for more than a brief interval, to avoid counting accidental suspensions).
  • Users are tracked anonymously, so the same user on different devices would be counted twice.
User UserContext 類別,描述此次 Session 的用戶資料,包括:AccountId、StoreRegion、UserAgent、Id…等。

Allows users to be counted. In a web app, if there is a cookie, the user Id is taken from that. If there isn't, a new one is generated. If your users have to login to your app, you could set the id from their authenticated ID, so as to provide a more reliable count that is correct even if the user signs in from a different machine.
Location LocationContext 類別,可取得 location IP。Identifies the geographic location of the device.
Flush() Normally the SDK sends data at times chosen to minimize impact on the user. However, in some cases you might want to flush the buffer - for example, if you are using the SDK in an application that shuts down.

可參考<使用 ApplicationInsights.config 或 .xml 設定 Application Insights SDK> 調整 TelemetryContext 的基本參數與相關資訊,
  • Session 單位被記算是當 App 被 suspended 就算一次,目前沒有限制一個 App 可緩存多少 Session,但仍然要注意可參考<資料保留和隱私權>。
  • User 屬性可操作 Session 的用戶為何,可記錄相關的參數。
    • 可以設定如 TelemetryClient.Context.User.Id 的屬性以追蹤使用者和工作階段。
    • 這項資訊會附加至執行個體所傳送的所有事件。
  • TelemetryClient 具備執行緒安全。


b. Track Event
     自定義的 Event 會被呈現於 Metrics Explorer ,包括:數量與明細,更可以透過 Diagnostic Search 搜尋指定的 Event Name 或設定的 property。
重要類別: EventTelemetry,相關的屬性有: Name、Properties、Metrics,Sequence 等用於描述該 Event 的特性。
藉由下列的程式範例來說明:
EventTelemetry eventItem = new EventTelemetry("play_button_click");
// 增加事件想標記的屬性,只有 1 K 的長度可以使用。
eventItem.Properties["type"] = "normal";
// 增加要測量的值
eventItem.Metrics.Add("Score", 100);

App.TelemetryClient.TrackEvent(eventItem);

這些設定可以在 dashboard 上查詢與搜尋,如下:
image

如果 Event 目的是觀查這個 Event 花了多少時間的話,可以參考:
var stopwatch = System.Diagnostics.Stopwatch.StartNew();

// ... perform the timed action ...
stopwatch.Stop();

var metrics = new Dictionary <string, double>
{{"processingTime", stopwatch.Elapsed.TotalMilliseconds}};
 
// Set up some properties:
var properties = new Dictionary <string, string> {{"signalSource", currentSignalSource.Name}};

// Send the event:
telemetry.TrackEvent("SignalProcessed", properties, metrics);


c. Track Metric
    藉由 TrackMetric 建立 metrics 的觀查,它與 TrackEvent 可以選擇使用,二者用途不完全相同 Mertic 可專心注意用戶使用的值與相關參數。
但它不能在 metric explorer 做搜尋特定的發生的內容,只能用於判斷關注的值的間距。
主要的元件為:MetricTelemetry,它提供定義觀測值的最大與最小,相關 Properties,實際值…等。藉由程式範例說明:
// 建立 MetricTelemetry  類別並給予對應的值
MetricTelemetry metricItem = new MetricTelemetry();
metricItem.Name = "user_game_score";
metricItem.Max = 100;
metricItem.Min = 0;
metricItem.Value = 30;
metricItem.Properties["game_name"] = "session 1";
metricItem.Properties["boss_type"] = "difficulty";
App.TelemetryClient.TrackMetric(metricItem);

顯示結果例如:
Add a new chart or select a chart, and under Custom select your metric


d. Track PageViews
     可用於觀察那些 Page 被載入過、載了多久,藉由 Properties 的屬性設定在該 Page 用戶做了那些事情或是特性,協助分析用戶的習慣。
例如:做 AB Test 或是觀察那些 Page 最常被用或載入過長等。藉由 dashboard 上可操作如下圖來觀查:
Usage lens on Overview blade

藉由 PageViewTelemetry 類別來操作:
PageViewTelemetry pageItem = new PageViewTelemetry();
pageItem.Name = "Test_A";
// 可設定用戶在該 Page 儲存了多久
pageItem.Duration = TimeSpan.FromSeconds(100);
pageItem.Url = new Uri("/MainPage.xaml", UriKind.Relative);
pageItem.Properties["navigatedParams"] = e.Parameter.ToString();
App.TelemetryClient.TrackPageView(pageItem);


e. Track Request
     可用於觀察 App 向 Server 請求 API 或是交易過程所花費的時間,更可以監控 HTTP Requests。例如:
// At start of processing this request:
// Operation Id is attached to all telemetry and helps you identify
// telemetry associated with one request:
telemetry.Context.Operation.Id = Guid.NewGuid().ToString();
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
// ... process the request ...

stopwatch.Stop();
telemetryClient.TrackRequest(requestName, DateTime.Now,stopwatch.Elapsed, "200", true); // Response code, success

 
f. Track Exception
try
{
...
}
catch (Exception ex)
{
    telemetry.TrackException(ex);
}
可直接補捉到 exception 的內容,如果在 App 的話,建議可以在 App.xaml.cs 中加上 UnhandledException 的事件可以回傳給 Application insights。


g. Track Trace
    除了上述提到一些特定用途的項目外,如果想要追蹤某些特殊自定義的內容,可以藉由 TrackTrace() 的方式來處理,
需要注意「The size limit on message is much higher than limit on properties. You can search on message content, but (unlike property values) you can't filter on it.」。
可藉由<Logs, exceptions and custom diagnostics for ASP.NET in Application Insights>的介紹來查詢與觀查需要的內容。
TraceTelemetry traceItem = new TraceTelemetry();
traceItem.Message = "用戶連線不穩定";
// 可設定 SeverityLevel
traceItem.SeverityLevel = SeverityLevel.Warning;
App.TelemetryClient.TrackTrace(traceItem);

上述說明了如何在自己的 App 加入一些觀查點,往下參考<Export telemetry from Application Insights>說明如何將匯入至 Storage 中的內容捉到自己的網站。

如何設定 Application Insights 的資料匯出至 Storage 請參考<Export telemetry from Application Insights>,但 Free 的用戶是沒有辦法自動匯出的。


〉存取指定 Storage 中的 Blob 資料
     匯出至 Storage 中的資料內容是 JSON 格式,例如:
{
"event": [
{
    "name": "invoke_playsong_logic",
    "count": 1
}
],
"internal": {
"data": {
  "id": "e1be3573-dd46-4a91-a8c6-404f88c8a2cc",
  "documentVersion": "1.5"
}},
"context": {
"device": {
"osVersion": "Other",
"type": "PC","browserVersion": "Other","screenResolution": {},


"userAgent": "NativeHost"


},


"application": {},
"location": {
"continent": "Asia",
"country": "Taiwan",
"point": {
"lat": 23.5,
"lon": 121
},
"clientip": "0.69.67.253",
"province": "",
"city": ""
},
"data": {
"isSynthetic": false,
"eventTime": "2015-07-09T09:42:49.0182941Z",
"samplingRate": 0
},
"operation": {},
"user": {
"accountId": "poulin@gmail.com",
"anonAcquisitionDate": "0001-01-01T00:00:00Z",
"authAcquisitionDate": "0001-01-01T00:00:00Z",
"accountAcquisitionDate": "0001-01-01T00:00:00Z"
},
"custom": {
"dimensions": [
{
"IsSuffle": "true"
},
{
"PlayType": "SpectIndex"
},
{
"DeveloperMode": "true"
}
],
"metrics": []
},
"session": {}
}
}

參考<How to use Blob storage from .NET>與<Programmatically access Blob storage>實作擷取匯出的資料。因此我建立一個 ASP.NET 的專案來擷取資料。

1. 首先了解輸出至 Storage 中的 Container 目錄與檔案結構為何,如下圖:
image

image

      往上圖可以看其結果為:
Container
       –> Dictionary
       –> Dictionary (PageView, Event 根據 Track 的項目有自己的目錄)
       –> Dictionary (日期)
       -->Dictionary (小時)
       –> Files (實際 Track 的內容,檔案為 *.blob,JSON 格式)

2. 建立一個 ASP.NET 專案,並加入 Windows Azure Storage 的 SDK。    image

3. 參考上面的檔案結構列出所有 *.blob 檔案內容;
protected void Unnamed_Click(object sender, EventArgs e)
{
ddlBlobFiles.Items.Clear();

// Retrieve storage account from connection string.
// 給予的 connection string 可以至 azure portal 找到 storage 裡面設定的 keys 參數
CloudStorageAccount storageAccount = 
CloudStorageAccount.Parse("DefaultEndpointsProtocol=https;AccountName=mystorage;AccountKey=NQLXZVsf42X3UknwYCSp5HmwAj2JjRfA==");

// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Retrieve reference to a previously created container.

// 指定 container
CloudBlobContainer container = blobClient.GetContainerReference("mystoragecontainer"); 
// Loop over items within the container and output the length and URI.
foreach (IListBlobItem item in container.ListBlobs(null, true, BlobListingDetails.All))
{
if (item.GetType() == typeof(CloudBlockBlob))
{
CloudBlockBlob blob = (CloudBlockBlob)item;
Console.WriteLine("Block blob of length {0}: {1}", blob.Properties.Length, blob.Uri);// 將取得的 blob 檔案取出


ddlBlobFiles.Items.Add(new ListItem


{
Text = blob.Name,
Value = blob.Uri.AbsoluteUri});
}
else if (item.GetType() == typeof(CloudPageBlob))
{
CloudPageBlob pageBlob = (CloudPageBlob)item;
 Console.WriteLine("Page blob of length {0}: {1}", pageBlob.Properties.Length, pageBlob.Uri);
}
else if (item.GetType() == typeof(CloudBlobDirectory))
{
CloudBlobDirectory directory = (CloudBlobDirectory)item;
Console.WriteLine("Directory: {0}", directory.Uri);
}
}
}
protected void ddlBlobFiles_SelectedIndexChanged(object sender, EventArgs e)
{
ListItem selected = ddlBlobFiles.SelectedItem;

// Retrieve storage account from connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=https;AccountName=mystorage;AccountKey=NQLXZVsfSgJLP6K1C7zhnvquDB+==");
// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

// Retrieve reference to a previously created container.
CloudBlobContainer container = blobClient.GetContainerReference("mystoragecontainer");
// Retrieve reference to a blob name
CloudBlockBlob blockBlob2 = container.GetBlockBlobReference(selected.Text);
 
string text;
using (var memoryStream = new MemoryStream())
{
blockBlob2.DownloadToStream(memoryStream);
text = System.Text.Encoding.UTF8.GetString(memoryStream.ToArray());
}
txtWrapContent.Text = text;
}
上述只是簡單舉了一個如何讀取被 export 到 container 的 blob,因為 Storage 儲存的空間有限,建議可以寫一個工具定時把資料取出加以分析。

======

[補充]

〉為 Universal App 加入 Application insights
    由於內鍵 VS2013 無法直接針對 Universal App 的專案 Template 加入 Application insights,我使用了以下的方式加以解決:

1.  建立三個專案:MyAppInsight(Universal App) 、TempWinApp (Windows App 8.1) 與 TemPhoneApp (Windows Phone App 8.1 ), 都是 runtime app:
     image

     其中 TemPhoneApp 與 TempWinApp 二個專案在建立時可勾選加入 Application insights settings,如下圖:
     image

    此時這二個專案都會自動由 NuGet 下載必要的 Application insights SDK、修改 *.csproj、建立 Config 等,例如:
    image
(這三個均為必要元件,在 Universal App 會少了 RuntimeTelemetry)。

    分別對 MyAppInsight 的 Windows 與 WindowsPhone 專案加入 Application Insights 的參考,如圖:    image

2. 開啟 MyAppInsight 中 windows phone 專案與 TempPhoneApp 專案的 *.csproj 進行二個檔案比對,並為 MyAppInsight  加入必要的參數至 *.csproj:

    2-1. 加入 <ApplicationInsightsResourceId/>。
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{8BA6ECD5-4171-4699-94C8-8FCF55203609}</ProjectGuid>
<OutputType>AppContainerExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MyAppInsight</RootNamespace>
<AssemblyName>MyAppInsight.WindowsPhone</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformVersion>8.1</TargetPlatformVersion>
<MinimumVisualStudioVersion>12</MinimumVisualStudioVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{76F1466A-8B6D-4E39-A767-685A06062A39};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>

<!-- 該段內容指定給 visual studio 知道如何整合工作加以連線 -->
<ApplicationInsightsResourceId>/subscriptions/c8b07204-1c7b-4c06-8035-fac11489576d/resourcegroups/TempWinApp/providers/microsoft.insights/components/TempWinApp</ApplicationInsightsResourceId>

<!-- -->
<SynthesizeLinkMetadata>true</SynthesizeLinkMetadata>
</PropertyGroup>

    2-2. 加入 <None Include="ApplicationInsights.config" /> 。
<ItemGroup>
<!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
<None Include="ApplicationInsights.config" />
<None Include="packages.config" />
</ItemGroup>

    2-3. 把 TempPhoneApp 專案中的 ApplicationInsights.config 複製到 Universal App 中 Windows 的目錄下,並且為 package.config 加入必要的參數:
            image

將 MyAppInsight 中對應專案的 Package.appmanifest 與 Package.config 分別 加入與 Temp 專案相同的 Microsoft.ApplicationInsights 參考。
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.ApplicationInsights" version="1.1.0" targetFramework="wpa81" />
<package id="Microsoft.ApplicationInsights.PersistenceChannel" version="1.1.0" targetFramework="wpa81" />
<package id="Microsoft.ApplicationInsights.WindowsApps" version="1.1.0" targetFramework="wpa81" />
<package id="Microsoft.ApplicationInsights.RuntimeTelemetry" version="0.14.0-build20632" targetFramework="wpa81" />
<package id="Microsoft.ApplicationInsights.WindowsPhone" version="0.14.0-build20632" targetFramework="wpa81" />
</packages>

3. 如果遇到 TelemetryClient 無法建立,可手動為 Universal App 中 Windows 專案加入「Microsoft.ApplicationInsights.Extensibility.RuntimeTelemetry」參考:

     路徑如下:C:\Users\{user name}\Documents\visual studio 2013\Projects\MyAppInsight\packages\Microsoft.ApplicationInsights.RuntimeTelemetry.0.14.0-build20632。

4.  開啟 App.xaml.cs 加入必要的程式碼,並且指定 InstrumentationKey。
public App()
{
TelemetryClient = new TelemetryClient();
TelemetryConfiguration.Active.TelemetryChannel.DeveloperMode = true;
// key 被放在 ApplicationInsights.config 裡
TelemetryClient.InstrumentationKey = "{application insight key";
}
     這是因為手動的方式 sdk 不會讀取到 ApplicationInsights.config 的 InstrumentationKey 值。

以上的方式雖然可以解決,但我個人一直覺得是因為 VS 2013 還不知道怎麼修改 Template,未來一定會被處理的。
=====
Application insights 對於如果需要對 apps 做一些觀查與分析是非常適用的。

而且分析的項目與維度我想應該能滿足大部分產品部門需要觀查的重點。希望對大家有所幫助。

References:
Add Application Insights to your device app project & Visual Studio Application Insights 文件
Application Insights for Windows Phone and Store apps
Application Insights - get started
Application Insights - 開始監視應用程式的健康情況和流量
Application Insights for Visual Studio Online
Announcing Application Insights Preview
Troubleshooting (重要)
Application Insights 中的資料收集、保留和儲存
在 Application Insights 中使用診斷搜尋
Application Insights 中 ASP.NET 的記錄檔、例外狀況和自訂診斷
Export telemetry from Application Insights
Unstructured Blob Storage (Building Real-World Cloud Apps with Azure)
How to use Blob storage from .NET

1 則留言: