簡體   English   中英

檢測Application Insights是否(以及為什么)可以將遙測數據發送到Azure

[英]Detecting whether or not (and why) Application Insights can send telemetry data to Azure

我正在開發Windows桌面應用程序,並已成功鏈接Application Insights Core程序集。 我正在使用TrackTraceTrackEvent等發送自定義遙測。

在某些工作站上,遙測已成功發送到Azure門戶,但在某些工作站上,遙測未成功,盡管對TrackTraceFlush等的調用成功(或至少返回而沒有引發異常TelemetryClient.IsEnabled()返回true。兩個工作站)使用具有相同端點https://dc.services.visualstudio.com/v2/trackInMemoryChannel ,發送間隔為30秒。

我可以在應用程序中調用以獲取TelemetryClient的連接狀態的API函數嗎? 這可能告訴我客戶端已成功連接,或者嘗試時遇到錯誤x ,並且仍有y個遙測數據包等待發送。

我不是在尋找像重新安裝NuGet程序包的清單(我做了...), 請確保您的防火牆允許流量流向端口xxx (它確實...)或嘗試安裝kb ... 871 (我做到了)太...)。 我想要的是一個狀態報告,我可以在我的應用程序運行時在客戶端工作站上的某個位置登錄,至少要在狀態欄中確認(是的,我知道狀態欄如今已經過時了)以至於出現了問題。

第一次更新-獲取隊列大小

第一個勝利,我能夠獲得隊列的大小。 我想做到這一點而沒有創建自己的渠道實現(尚未)。 但是,這對檢測中斷幾乎沒有幫助,因為即使發送器無法發送遙測項目(它將直接丟棄它們),隊列也會耗盡(稍后會詳細介紹)。 至少您知道發送器線程正在運行...

private ITelemetryChannel _TelemetryChannel;
private InMemoryChannel _InMemoryChannel;
private object _TelemetryBuffer;
private object _BufferLock;
private object _InMemoryTransmitter;

_TelemetryChannel = TelemetryConfiguration.Active?.TelemetryChannel;
if (_TelemetryChannel != null && _TelemetryChannel is InMemoryChannel)
{
  _InMemoryChannel = (InMemoryChannel)_TelemetryChannel;
  _TelemetryBuffer = GetInstanceField (_InMemoryChannel, "buffer");
  _BufferLock = GetInstanceField (_TelemetryBuffer, "lockObj");
  _InMemoryTransmitter = GetInstanceField (_InMemoryChannel, "transmitter");
}

public int GetTelemetryQueueSize ()
{
    if (_BufferLock != null)
    {
        lock (_BufferLock)
        {
            object l = GetInstanceField (_TelemetryBuffer, "items");
            if (l is List<ITelemetry>)
            {
                return ((List<ITelemetry>)l).Count;
            }
        }
    }
    return -1;
}

您還需要一個實用程序函數,以使用反射來訪問對象的私有字段(緩沖區和發送器是internal sealed ……)我使它們盡可能地抗錯誤,它們可能更簡潔。

private static object GetInstanceField (Type type, object instance, string fieldName)
{
    if (instance == null)
    {
        return null;
    }
    try
    {
        BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
        FieldInfo field = type.GetField (fieldName, bindFlags);
        return field.GetValue (instance);
    }
    catch
    {
        return null;
    }
}

private static object GetInstanceField (object instance, string fieldName)
{
    if (instance == null)
    {
        return null;
    }
    return GetInstanceField (instance.GetType (), instance, fieldName);
}

好的,我設法使其工作了……沒有API可以做到,所以我創建了一個新的自定義遙測通道,該通道實際報告錯誤,並且可以依靠。

編輯:從注釋中可以看出ReliableTelemetryChannel不是此類的適當名稱。 它應命名為ProbingTelemetryChannel 謝謝。

using System;
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.Extensibility.Implementation;

namespace Streambolics.Telemetry
{
  public class ReliableTelemetryChannel : ITelemetryChannel
  {
    private Uri _EndpointAddress;
    private int _Attempts, _Successes, _Failures;
    private Exception _LastFailure;
    private DateTime _LastFailureTime;

    public ReliableTelemetryChannel ()
    {
      EndpointAddress = TelemetryConfiguration.Active?.TelemetryChannel?.EndpointAddress;
    }

    public bool? DeveloperMode {
        get { return true; }
        set { }
    }

    public string EndpointAddress {
        get { return _EndpointAddress?.ToString (); }
        set {
            if (String.IsNullOrEmpty (value))
                _EndpointAddress = null;
            else
                _EndpointAddress = new Uri (value);
        }
    }

    public void Flush () { }

    public void Send (ITelemetry item)
    {
      _Attempts++;

      try
      {
        item.Timestamp = DateTime.Now;
        byte[] data = JsonSerializer.Serialize (new ITelemetry[] { item });
        var transmission = new Transmission (_EndpointAddress, data, "application/x-json-stream", JsonSerializer.CompressionType);
        transmission.SendAsync ().GetAwaiter ().GetResult ();
        _Successes++;
      }
      catch (Exception ex)
      {
          _Failures++;
          _LastFailure = ex;
          _LastFailureTime = DateTime.Now;
      }
    }

    protected virtual void Dispose (bool disposing) { }
    public void Dispose ()
    { Dispose (true); }
  }
}

現在只需要創建頻道和該頻道上的客戶即可:

var _ReliableChannel = new ReliableTelemetryChannel ();
var _ReliableConfiguration = new TelemetryConfiguration ();
_ReliableConfiguration.TelemetryChannel = _ReliableChannel;
var _ReliableClient = new TelemetryClient (_ReliableConfiguration);
_ReliableClient.InstrumentationKey = "...";

現在,我只是定期發送一個探針,並查詢通道以獲取錯誤統計信息:

_ReliableClient.TrackEvent ("TelemetryProbe");
GlobalLog.Log ("Probe attempts {0} Last Error {1}", _ReliableChannel.Attempts, _ReliableChannel.LastFailure);

它不能解決檢測活動配置是否有效的全局問題(我用來發送常規遙測,使用緩沖等),但是至少我可以安全地假設,如果我的可靠通道正常工作,則常規通道也正在工作。

注意:我寫完這篇文章后不久就停止了持久性通道。

您可以使用它,但是您要做的就是創建一個已經存在的持久性通道。

您應該執行以下操作:

  using Microsoft.ApplicationInsights.Channel;
  using Microsoft.ApplicationInsights.Extensibility;
  ...

  // Set up 
  TelemetryConfiguration.Active.InstrumentationKey = "YOUR INSTRUMENTATION KEY";

  TelemetryConfiguration.Active.TelemetryChannel = new PersistenceChannel();

在應用程序退出時,請確保您致電

telemetryClient.Flush()

將遙測數據刷新到通道。

這是將遙測數據寫入磁盤,並定期將數據刷新到Azure雲。 這非常適合間歇性的Internet連接,也適用於在發送所有數據之前關閉應用程序的情況。

在啟動時,您可以添加一個微小的睡眠延遲,以確保將來自先前會話的數據發送到雲。

該代碼示例摘自Application Insights文檔 ,該文檔提供了更多詳細信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM