我正在开发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);
}
答案 0 :(得分:1)
好的,我设法让它工作......没有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);
它没有解决检测活动配置是否有效的全局问题(我用来发送常规遥测,缓冲等),但至少我可以放心地假设我的Reliable频道是工作,常规工作也在工作。
答案 1 :(得分:1)
注意:持久性通道在我写完后不久就停止了。
你得到它的工作,但你所做的只是创建一个已经存在的持久性通道。
您应该完成以下操作:
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 Documentation,可以找到更多详细信息。