Detectar si o no (y por qué) Application Insights puede enviar datos de telemetría a Azure

Estoy desarrollando una aplicación de escritorio de Windows y he vinculado con éxito los conjuntos de Application Insights Core. Estoy usando TrackTrace , TrackEvent , etc. para enviar telemetría personalizada.

En algunas estaciones de trabajo, la telemetría se envía con éxito al portal de Azure y en otras no, aunque las llamadas a TrackTrace , Flush , etc. tienen éxito (o al menos regresan sin lanzar una excepción. TelemetryClient.IsEnabled() devuelve true. Ambas estaciones de trabajo use un InMemoryChannel , con el mismo punto final https://dc.services.visualstudio.com/v2/track y el intervalo de envío es de 30 segundos.

¿Hay alguna función de API a la que pueda llamar en mi aplicación para obtener el estado de conexión del TelemetryClient? Algo que me diría que el cliente está conectado correctamente, o que encontró un error x al intentarlo, y aún tiene y paquetes de telemetría esperando para ser enviados.

No estoy buscando una lista de verificación como reinstalar el paquete NuGet (lo hice …), asegúrese de que su firewall permita el tráfico al puerto xxx (lo hace …) o intente instalar kb … 871 (hice eso también…). Lo que me gustaría es un informe de estado que pueda registrar en algún lugar de la estación de trabajo cliente mientras mi aplicación se ejecuta, al menos reconociendo en la barra de estado (Sí, sé que las barras de estado son tan antiguas como hoy en día) que hay un problema.

Primera actualización – Obtención del tamaño de la cola

Primera victoria, pude obtener el tamaño de la cola. Quería hacer eso sin crear mi propia implementación de canal (todavía). Sin embargo, esto es de poca ayuda para detectar interrupciones, ya que la cola se agotará incluso si el transmisor no puede transmitir los elementos de telemetría (simplemente los descartará), más sobre esto más adelante. Al menos sabes que el hilo del transmisor está corriendo …

 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) { return ((List)l).Count; } } } return -1; } 

También necesita una función de utilidad para usar la reflexión para acceder a los campos privados de los objetos (el búfer y el transmisor están internal sealed …) Los hice tan resistentes a los errores como sea posible, podrían ser más concisos.

 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); } 

De acuerdo, logré que funcionara … No hay una API para hacerlo, así que creé un nuevo canal de telemetría personalizado que informa los errores y en el que puedo confiar.

Editar: de los comentarios se desprende que ReliableTelemetryChannel no es un nombre apropiado para esta clase. Debería llamarse ProbingTelemetryChannel . Gracias.

 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); } } } 

Ahora solo es cuestión de crear el canal y un cliente en ese canal:

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

Ahora simplemente envío una sonda y pregunto en el canal las estadísticas de error:

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

No resuelve el problema global de detectar si la configuración activa funciona (la que uso para enviar telemetría regular, con búfer, etc.), pero al menos puedo asumir con seguridad que si mi canal confiable está funcionando, el normal esta trabajando tambien

Nota: el canal de persistencia se suspendió poco después de que escribí esto.

Lo tienes para funcionar, pero todo lo que hiciste fue crear un canal de persistencia que ya existe.

Deberías haber hecho lo siguiente:

  using Microsoft.ApplicationInsights.Channel; using Microsoft.ApplicationInsights.Extensibility; ... // Set up TelemetryConfiguration.Active.InstrumentationKey = "YOUR INSTRUMENTATION KEY"; TelemetryConfiguration.Active.TelemetryChannel = new PersistenceChannel(); 

En la aplicación Salir, asegúrese de llamar al

 telemetryClient.Flush() 

para descargar los datos de telemetría al canal.

Lo que esto hace es escribir sus datos de telemetría en el disco y descargar periódicamente los datos a la nube de Azure. Esto es excelente para la conectividad a Internet intermitente y también para los casos en que la aplicación se cierra antes de que se envíen todos los datos.

En el inicio, puede agregar un pequeño retraso de suspensión para asegurarse de que los datos de una sesión anterior se envíen a la nube.

Los ejemplos de código se han tomado de la documentación de Application Insights, donde se pueden encontrar más detalles.