正在检测Application Insights是否(以及为什么)可以向Azure发送遥测数据
本文关键字:Azure 可以向 数据 为什么 Application 检测 Insights 是否 | 更新日期: 2023-09-27 18:27:59
我正在开发一个Windows桌面应用程序,并已成功链接application Insights Core程序集。我使用TrackTrace
、TrackEvent
等发送自定义遥测。
在一些工作站上,遥测已成功发送到Azure门户,而在另一些工作站上则没有,尽管对TrackTrace
、Flush
等的调用成功(或至少返回而不引发异常。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);
}
好吧,我设法让它工作。。。没有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文档,在该文档中可以找到更多详细信息。