正在检测Application Insights是否(以及为什么)可以向Azure发送遥测数据

本文关键字:Azure 可以向 数据 为什么 Application 检测 Insights 是否 | 更新日期: 2023-09-27 18:27:59

我正在开发一个Windows桌面应用程序,并已成功链接application Insights Core程序集。我使用TrackTraceTrackEvent等发送自定义遥测。

在一些工作站上,遥测已成功发送到Azure门户,而在另一些工作站上则没有,尽管对TrackTraceFlush等的调用成功(或至少返回而不引发异常。TelemetryClient.IsEnabled()返回true。两个工作站都使用InMemoryChannel,具有相同的端点https://dc.services.visualstudio.com/v2/track,发送间隔为30秒。

是否有API函数可以在应用程序中调用以获取TelemetryClient的连接状态?它会告诉我客户端已成功连接,或者在尝试时遇到错误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);
}

正在检测Application Insights是否(以及为什么)可以向Azure发送遥测数据

好吧,我设法让它工作。。。没有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云。这非常适合间歇性的互联网连接,也适用于应用程序在发送所有数据之前关闭的情况。

在启动时,您可以添加一个微小的睡眠延迟,以确保前一个会话的数据发送到云。

代码示例取自Application Insights文档,在该文档中可以找到更多详细信息。