El trabajo en una aplicación no termina cuando el desarrollo de la misma acaba. Una vez publicada es muy importante poder detectar problemas, conocer el rendimiento de la aplicación, saber qué hacen los usuarios con ella, qué secciones son las más visitadas… todo con el fin de ir introduciendo paulatinamente mejoras y adaptarnos a las preferencias de la gente que la utiliza.

Existen varios servicios que nos permiten, de manera sencilla, incluir esta posibilidad de monitorización en nuestras aplicaciones universales.

Application Insights

Es la solución de Microsoft para llevar a cabo la monitorización de tus aplicaciones. Nos proporciona tanto servicios de APM (Application Performance Monitoring), es decir, análisis de rendimiento y problemas de nuestra aplicación, como datos de uso: secciones más visitadas, procedencia de los usuarios, tiempo de las sesiones, etc.

La integración de Application Insights en una aplicación universal es una tarea realmente sencilla.

En primer lugar, tenemos que crear un nuevo servicio de Application Insights en nuestra suscripción de Azure. Para ello, entramos en nuestra cuenta de Azure en el nuevo portal de vista previa (https://portal.azure.com/). Si entramos al antiguo portal, siempre podemos cambiarnos al portal de vista previa:

clip_image001

Una vez en el portal de vista previa, pinchamos en Nuevo -> Servicios de desarrollo –> Application Insights.

clip_image002

Se nos desplegará un nuevo menú para configurar nuestro servicio de Application Insights. Nosotros, en este ejemplo, vamos a introducirlo en una aplicación universal, con lo que utilizaremos la misma Instrumentation Key tanto para la aplicación de Windows Phone como para la de Windows Store. Al tratarse de una aplicación universal, con una funcionalidad similar en ambas aplicaciones, es interesante tener todos los datos recogidos en el mismo lugar. Sin embargo, si por circunstancias específicas se desea que los datos de cada versión vayan por separado, bastaría con utilizar dos Instrumentation Key, una para cada versión.

clip_image004

En este nuevo menú, elegimos un nombre para el servicio, el tipo de aplicación a monitorizar (en nuestro caso “Aplicación de la Tienda Windows” o “Aplicación de Windows Phone”) y pinchamos en Crear.

Una vez se haya creado, vamos a las propiedades de la configuración del servicio. Una vez allí, copiamos la clave de instrumentación que es la que necesitamos indicarle a nuestras aplicaciones para que trabaje con el servicio de Application Insights creado.

clip_image006

Como vemos en la imagen, todavía no nos aparece ningún dato ya que no tenemos ninguna aplicación vinculada que vaya generando los mismos.

Con ello, hemos finalizado la configuración en el portal de Azure y pasamos directamente a Visual Studio.

En Visual Studio, creamos nuestra aplicación universal del modo habitual (File->New->Project), seleccionamos Universal Apps, elegimos el nombre de nuestra aplicación y pinchamos en Ok:

clip_image008

Una vez creado el proyecto, añadimos el paquete de NuGet “Application Insights for Windows Applications” tanto en el proyecto de Windows Phone como en el de Windows Store. Por supuesto, podemos usar el API de Insights desde nuestro proyecto Shared.

clip_image010

El siguiente paso es inicializar el servicio cuando arranque nuestra aplicación. Para ello, nos vamos al proyecto Shared y abrimos el fichero App.xaml.cs

clip_image012

Nos vamos al constructor y añadimos la inicialización de nuestro servicio de Application Insights:

[code language=”csharp”]
public App()
{
this.InitializeComponent();
this.Suspending += this.OnSuspending;

// Initialize application insights
WindowsAppInitializer.InitializeAsync("<APP INSIGHTS INTRUMENTATION KEY>",
WindowsCollectors.Metadata |
WindowsCollectors.PageView |
WindowsCollectors.Session |
WindowsCollectors.UnhandledException);
}
[/code]

Como vemos, en el inicializador podemos indicarle una serie de Collectors, que configuran los diferentes tipos de datos que se van a recolectar de forma automática: metadatos, visualizado de páginas, sesión y excepciones no controladas. Por defecto están todos seleccionados, aunque podemos elegir aquellos que más nos interesen.

Con ello, tendríamos configurado de forma básica el servicio de Applications Insights. Si ejecutamos nuestra aplicación, empezarán a llegar datos a Azure, que podremos visualizar en el portal.

clip_image014

Usando el api para enviar eventos Customizados y métricas

Si sólo pudiéramos monitorizar los eventos por defecto, el incorporar Application Insights a nuestra aplicación seguiría siendo útil, pero limitado. Sin embargo, es posible añadir eventos personalizados de manera muy sencilla. El API nos ofrece los siguientes métodos:

Método Descripción
TrackPageView Registra cuando se visualiza una nueva página de la aplicación
TrackEvent Registra cualquier tipo de evento
TrackMetric Registra medidas no relacionadas a un evento concreto
TrackException Registra cuando se ha producido una excepción
TrackRequest Registra la frecuencia y duración de las llamadas a servidor
TrackTrace Registra logs
TrackDependency Registra las llamadas y la duración de las mismas a componentes de terceros

Para mostrar cómo registrar datos utilizando estos métodos vamos a añadir funcionalidad básica a nuestra aplicación de ejemplo. En este caso, vamos a tener una aplicación de contactos. En la página inicial tendremos una lista con nuestros contactos y si pinchamos en uno de ellos pasaríamos al detalle del contacto seleccionado. Así mismo, se podrán añadir contactos, hasta un máximo de 10. Si queremos añadir más saltará una excepción y se mostrará un mensaje.

Lo primero que haremos es inicializar una variable del tipo TelemetryClient en nuestro ViewModelBase, con lo cual podremos usarla en todos nuestros View Models para registrar los datos deseados:

Ahora, imaginemos que deseamos registrar cuando un usuario añada un nuevo contacto. Para ello, en nuestro MainViewModel, en el comando correspondiente a añadir un nuevo contacto (AddContactCommand) utilizaríamos el siguiente código:

[code language=”csharp”]
_telemetryClient.TrackEvent("Add Contact");
[/code]

Donde Add Contact es el nombre con el que queremos que sea registrado el comando.

Así mismo, podemos añadir a esta llamada lo que se conocen como propiedades y métricas. Las propiedades son un conjunto de strings que posteriormente nos servirán para filtrar los eventos. Las métricas, por su parte, son valores numéricos que luego podrán representarse de forma gráfica a la hora de analizar los resultados. Por ejemplo, añadamos en nuestra llamada si el nuevo contacto se ha creado desde la aplicación Windows Phone o desde la aplicación de Windows Store. Así mismo, podemos añadir el número de contactos del usuario que ha añadido el contacto nuevo. Para ello, dentro del mismo comando anterior, sustituimos la línea de código antes comentada por las siguientes:

[code language=”csharp”]
var properties = new Dictionary<string, string>();
var metrics = new Dictionary<string, double>();
#if WINDOWS_PHONE_APP
properties.Add("App","Windows Phone");
#endif
#if WINDOWS_APP
properties.Add("App", "Windows App");
#endif
metrics.Add("Number of Contacts", Contacts.Count);
_telemetryClient.TrackEvent("Add Contact",properties,metrics);
[/code]

Como vemos, al declarar tanto las propiedades y las métricas como diccionarios podemos añadir el número de pares clave-valor que deseemos para asegurar la correcta clasificación de todos los eventos que queramos registrar. Este ejemplo es poco útil, ya que por defecto, Applications Insights clasifica por el dispositivo que hace la llamada, sin embargo, es bastante ilustrativo de la utilidad de las propiedades y métricas a la hora de enviar un evento.

Igualmente podemos registrar el caso de que se produzca la excepción al intentar añadir más de 10 contactos. En nuestro caso hemos definido una excepción llamada ContactLimitException que será la que se lance cuando se intenten añadir más de diez contactos. El código quedará de la siguiente forma:

[code language=”csharp”]
catch (ContactLimitException e)
{
_telemetryClient.TrackException(e);
new MessageDialog("Can´t add more than 10 contacts").ShowAsync();
}
[/code]

Al igual que en el caso anterior, podemos añadir propiedades y métricas a esta llamada para permitir mayor profundidad en los datos que se están registrando. La potencia de estos sistemas radica en que, por ejemplo, tras un cierto tiempo después de la publicación de la aplicación observamos un alto índice de este tipo de excepción. Eso significaría que nuestros usuarios en gran número desean poder añadir más de diez contactos. ¿No crees que sería un buen momento de actualizar la aplicación añadiendo esta funcionalidad?

Google Analytics

La forma de operar con Google Analytics es similar a la que hemos descrito con Applications Insights. Lo primero que tenemos que hacer es registrar nuestra aplicación en la página de Analytics : http://www.google.com/analytics/. Iniciamos sesión con nuestra cuenta de Google o nos creamos una cuenta nueva. Al hacerlo, navegaremos a la siguiente página:

clip_image016

En ella, pulsamos en “regístrese” para pasar a la página de registro de nuestra aplicación:

clip_image018

Elegiremos las preferencias deseadas. En nuestro caso, será una aplicación para móviles y fijaremos el nombre de la cuenta y el nombre de la aplicación, la categoría del sector y la zona horaria para los informes. Clickamos en obtener id de seguimiento y, tras aceptar los términos y condiciones, pasamos a la página de administración de nuestra recién creada cuenta.

clip_image020

Ese Id de seguimiento actúa de forma similar a la clave de instrumentación de Applications Insights y es el valor que hemos de introducir en la configuración de nuestra aplicación para asociarla a la cuenta de Google Analytics de forma correcta para empezar a registrar los datos y eventos que se produzcan en la misma.

Volvemos a Visual Studio y a nuestra aplicación de ejemplo e instalamos el SDK de Google Analytics como paquete NuGet (este proceso lo tenemos que hacer tanto para la aplicación de Windows Phone como para la aplicación de Windows Store):

clip_image022

Al incluir esta librería, se nos añaden dos archivos en la raíz de nuestras aplicaciones (analytics.xsd y analytics.xml). Este último es el que nos interesa:

[code language=”xml”]
<?xml version="1.0" encoding="utf-8" ?>
<!–More info at https://developers.google.com/analytics/devguides/collection/android/v2/parameters–>
<analytics xmlns="http://googleanalyticssdk.codeplex.com/ns/easytracker">
<!–Replace placeholder ID with your tracking ID–>
<trackingId>UA-XXXX-Y</trackingId>
<!–Replace placeholder name with your app name. If you leave this empty your package name (Windows.ApplicationModel.Package.Current.Id.Name) will be used–>
<!–<appName>Test</appName>–>
<!–Replace placeholder version with your app version. If you leave this empty your package version (Windows.ApplicationModel.Package.Current.Id.Version) will be used–>
<!–<appVersion>1.0.0.0</appVersion>–>
<!–Optionally supply the application ID–>
<!–<appId>com.company.app</appId>–>
<!–Optionally supply the installer ID for this app.–>
<!–<appInstallerId>com.platform.vending</appInstallerId>–>
<!–Enable writing of debug information to debug window log, useful for troubleshooting your implementation. Default is false.–>
<!–<debug>false</debug>–>
<!–The dispatch period in seconds. Default is 0 (indicating to send logs immediately)–>
<!–<dispatchPeriod>30</dispatchPeriod>–>
<!–The dispatch period in seconds. Values must be between 0.0 and 100.0 Default is 100.0–>
<!–<sampleFrequency>100.0</sampleFrequency>–>
<!–Tells Google Analytics to anonymize the information sent by the tracker objects by removing the last octet of the IP address prior to its storage. Note that this will slightly reduce the accuracy of geographic reporting. Default is false.–>
<!–<anonymizeIp>false</anonymizeIp>–>
<!–Enable automatic exception tracking. Default is false.–>
<!–<reportUncaughtExceptions>false</reportUncaughtExceptions>–>
<!–The amount of time (in seconds) your application can stay in the background before the session is ended. Negative value disables EasyTracker session management. Default is 30–>
<!–<sessionTimeout>30</sessionTimeout>–>
<!–Enable automatic app lifetime tracking (e.g. suspend/resume). Default is false.–>
<!–<autoAppLifetimeTracking>false</autoAppLifetimeTracking>–>
<!–Enable automatic app lifetime monitoring (e.g. suspend/resume). If true, all dispatched events will be sent on suspend and session timeout will be honored.
true by default; must be true if autoAppLifetimeTracking is true.–>
<!–<autoAppLifetimeMonitoring>true</autoAppLifetimeMonitoring>–>
<!–Enables automatic network connectivity monitoring and avoids sending logs while not connected. Default is true.–>
<!–<autoTrackNetworkConnectivity>true</autoTrackNetworkConnectivity>–>
<!–Enable HTTPS instead of HTTP if true, causes all hits to be sent to the secure (SSL) Google Analytics endpoint. Default is false.–>
<!–<useSecure>false</useSecure>–>
</analytics>
[/code]

Entre los diferentes parámetros que podemos configurar, el que nos interesa es el de trackingId, donde introduciremos el número de seguimiento que hemos obtenido anteriormente desde la página de Google Analytics.

Con ello, ya tenemos todo lo necesario para monitorizar los eventos, visionado de páginas, excepciones… tal y como hacíamos en Applications Insights.

Añadir visionado de páginas:

GoogleAnalytics.EasyTracker.GetTracker().SendView(“Nombre de la página”);

En nuestro caso, en cada método Navigated de nuestros View Models añadiremos la línea de código anterior (identificando correctamente el nombre de la página). Quedaría de la siguiente forma:

MainViewModel:

[code language=”csharp”]
public override void Navigated(object parameter)
{
GoogleAnalytics.EasyTracker.GetTracker().SendView("MainView");
}
[/code]

ContactDetailsViewModel:

[code language=”csharp”]
public async override void Navigated(object parameter)
{
GoogleAnalytics.EasyTracker.GetTracker().SendView("ContactDetailsView");
if (parameter is int)
{
var contactId = (int) parameter;
Contact = await _repository.GetContactById(contactId);
}
}
[/code]

Añadir monitorización de eventos:

[code language=”csharp”]
GoogleAnalytics.EasyTracker.GetTracker().SendEvent(Categoría,Acción,Etiqueta, Valor);
[/code]

En nuestro ejemplo, añadiremos también para monitorizar el evento de añadir un Nuevo contacto. Quedaría de la siguiente forma:

[code language=”csharp”]
#if WINDOWS_PHONE_APP
GoogleAnalytics.EasyTracker.GetTracker().SendEvent("Windows Phone", "Add Contact", null, Contacts.Count);
#endif
#if WINDOWS_APP
GoogleAnalytics.EasyTracker.GetTracker().SendEvent("Windows App", "Add Contact", null, Contacts.Count);
#endif
[/code]

Monitorización de excepciones:

[code language=”csharp”]
GoogleAnalytics.EasyTracker.GetTracker().SendException(Mensaje,false);
[/code]

El valor booleano, indica si la excepción es crítica o no. En nuestro caso, al igual que hacíamos con Applications Insights, lo lanzaremos cuando un usuario quiera añadir más de diez contactos:

[code language=”csharp”]
catch (ContactLimitException e)
{
GoogleAnalytics.EasyTracker.GetTracker().SendException("More than 10 contacts", false);
new MessageDialog("Can´t add more than 10 contacts").ShowAsync();
}
[/code]

Otras monitorizaciones:

Al igual que en Applications Insights, aparte de las monitorizaciones básicas que hemos señalado, se pueden trackear más eventos o usos de la aplicación. Por ejemplo:

– Inicio de sesión:

[code language=”csharp”]
GoogleAnalytics.EasyTracker.GetTracker().StartSession()
[/code]

– Fin de sesión:

[code language=”csharp”]
GoogleAnalytics.EasyTracker.GetTracker().EndSession()
[/code]

– Control del tiempo de ejecución de una transacción:

[code language=”csharp”]
GoogleAnalytics.EasyTracker.GetTracker().SendTiming();
[/code]

– Interacción con redes sociales:

[code language=”csharp”]
GoogleAnalytics.EasyTracker.GetTracker().SendSocial();
[/code]

– Realización de una transacción (por ejemplo compras dentro de la aplicación):

[code language=”csharp”]
GoogleAnalytics.EasyTracker.GetTracker().Transaction();
[/code]

Conclusión

La inclusión de un servicio de monitorización se hace imprescindible para realizar un correcto seguimiento de cómo se está desenvolviendo nuestra aplicación y si ésta está satisfaciendo a nuestros usuarios. Así mismo, nos ofrece, mediante un análisis detallado de los datos registrados, ideas y patrones a seguir para mejorar nuestro desarrollo y llegar a un número mayor de personas y que, de forma simultánea, el grado de satisfacción de nuestros usuarios con la aplicación aumente.

En este pequeño artículo, hemos dado una visión somera, a modo de introducción, de cómo podemos trabajar con Google Analytics y Applications Insights en nuestras aplicaciones universales. Si es de vuestro interés, en posteriores artículos, podríamos detallar cómo configurar gráficos para obtener información relevante, cómo poder exportar los datos obtenidos para analizarlos con otras herramientas, cómo añadir más métricas, o, incluso, hablar de otros servicios de monitorización existentes.

Happy tracking!

Fran Olmedo (@fmolmedo)

Recursos

Código de la aplicación de ejemplo: https://github.com/franmolmedo/Tracking

Google analytics SDK for Windows 8 and Windows Phone: https://googleanalyticssdk.codeplex.com/

Documentación Application insights: https://azure.microsoft.com/en-us/documentation/articles/app-insights-windows-get-started/