Supervisión y telemetría (creación de aplicaciones en la nube reales con Azure)

por Rick Anderson y Tom Dykstra

Descargar proyecto Fix It o Descargar libro electrónico

El libro electrónico Compilar aplicaciones en la nube del mundo real con Azure se basa en una presentación desarrollada por Scott Guthrie. Explica 13 patrones y prácticas que pueden ayudarle a tener éxito en el desarrollo de aplicaciones web para la nube. Para obtener información sobre el libro electrónico, consulte el primer capítulo.

Muchas personas dependen de los clientes para informarles cuándo su aplicación está inactiva. No es realmente un procedimiento recomendado en ningún lugar y, especialmente, no en la nube. No hay ninguna garantía de notificación rápida y, cuando se recibe una notificación, a menudo se obtienen datos mínimos o engañosos sobre lo que ha ocurrido. Con los buenos sistemas de telemetría y registro, puede tener en cuenta lo que sucede con la aplicación y cuando algo va mal, descubre inmediatamente y tiene información de solución de problemas útil con la que trabajar.

Compra o alquiler de una solución de telemetría

Nota:

Este artículo se escribió antes de que se publicara Application Insights. Application Insights es el enfoque preferido para las soluciones de telemetría en Azure. Consulte Configuración de Application Insights para el sitio web de ASP.NET para obtener más información.

Una de las cosas que es genial sobre el entorno de nube es que es realmente fácil comprar o alquilar su manera de victoria. La telemetría es un ejemplo. Sin mucho esfuerzo, puede poner en marcha un sistema de telemetría realmente bueno, muy rentable. Hay muchos asociados excelentes que se integran con Azure y algunos de ellos tienen niveles gratuitos, por lo que puede obtener telemetría básica para nada. Estas son solo algunas de las disponibles actualmente en Azure:

Microsoft System Center también incluye características de supervisión.

Le guiaremos rápidamente a través de la configuración de New Relic para mostrar lo fácil que puede ser usar un sistema de telemetría.

En el Portal de administración de Azure, regístrese en el servicio. Haga clic en Nuevo, y a continuación, haga clic en Almacenar. Aparece el cuadro de diálogo Elegir un complemento. Desplácese hacia abajo y haga clic en New Relic.

Choose an Add-on

Haga clic en la flecha derecha y elija el nivel de servicio que desee. Para esta demostración, usaremos el nivel gratis.

Personalize add-on

Haga clic en la flecha derecha, confirme la "compra" y New Relic ahora aparece como complemento en el portal.

Review purchase

New Relic add-on in management portal

Haga clic en Informaciónde conexión y copie la clave de licencia.

Connection info

Vaya a la pestaña Configurar de la aplicación web en el portal, establezca Supervisión de rendimiento en Complemento y establezca la lista desplegable Elegir complemento en New Relic. A continuación, haga clic en Save(Guardar).

New Relic in Configure tab

En Visual Studio, instale el paquete NuGet de New Relic en la aplicación.

Developer analytics in Configure tab

Implemente la aplicación en Azure y empiece a usarla. Cree algunas tareas de corrección para proporcionar alguna actividad para que New Relic supervise.

A continuación, vuelva a la página New Relic en la pestaña Complementos del portal y haga clic en Administrar. El portal le envía al portal de administración de New Relic, mediante el inicio de sesión único para la autenticación, por lo que no tiene que volver a escribir sus credenciales. La página Información general presenta una variedad de estadísticas de rendimiento. (Haga clic en la imagen para ver el tamaño completo de la página de información general).

New Relic Monitoring tab

Estas son solo algunas de las estadísticas que puede ver:

  • Tiempo medio de respuesta en diferentes horas del día.

    Response time

  • Velocidades de rendimiento (en solicitudes por minuto) en diferentes horas del día.

    Throughput

  • Tiempo de CPU del servidor dedicado a controlar diferentes solicitudes HTTP.

    Web Transaction times

  • Tiempo de CPU invertido en diferentes partes del código de la aplicación:

    Trace details

  • Estadísticas históricas de rendimiento.

    Historical performance

  • Llamadas a servicios externos, como Blob service y estadísticas sobre la confiabilidad y capacidad de respuesta del servicio.

    External services

    External services2

    External service

  • Información sobre dónde proviene el mundo o dónde procede el tráfico de la aplicación web de Estados Unidos.

    Geography

También puede configurar informes y eventos. Por ejemplo, puede decir que cada vez que empiece a ver errores, envíe un correo electrónico para alertar al personal de soporte técnico al problema.

Reports

New Relic es solo un ejemplo de un sistema de telemetría; también puede obtener todo esto de otros servicios. La belleza de la nube es que sin tener que escribir ningún código, y para un gasto mínimo o sin gastos, de repente puede obtener mucha más información sobre cómo se usa la aplicación y qué están experimentando realmente los clientes.

Registro de información

Un paquete de telemetría es un buen primer paso, pero todavía tiene que instrumentar su propio código. El servicio de telemetría le indica cuándo hay un problema y le indica lo que están experimentando los clientes, pero es posible que no le proporcione mucha información sobre lo que está ocurriendo en el código.

No quiere tener que realizar la conexión remota en un servidor de producción para ver lo que hace la aplicación. Esto podría ser práctico cuando tiene un servidor, pero ¿qué ocurre cuando se ha escalado a cientos de servidores y no sabe en qué se debe realizar el remoto? El registro debe proporcionar suficiente información que nunca tenga que realizar de forma remota en los servidores de producción para analizar y depurar problemas. Debe registrar suficiente información para que pueda aislar los problemas únicamente a través de los registros.

Entrar en producción

Muchas personas activan el seguimiento en producción solo cuando hay un problema y quieren depurar. Esto puede introducir un retraso considerable entre el momento en que conoce un problema y el tiempo que obtiene información útil sobre la solución de problemas. Y es posible que la información que obtenga no sea útil para errores intermitentes.

Lo que se recomienda en el entorno en la nube donde el almacenamiento es barato es que siempre deja el registro en producción. De este modo, cuando se producen errores, ya se han registrado y tiene datos históricos que pueden ayudarle a analizar problemas que se desarrollan con el tiempo o se producen regularmente en momentos diferentes. Puede automatizar un proceso de purga para eliminar los registros antiguos, pero es posible que sea más caro configurar este proceso que para mantener los registros.

El gasto agregado del registro es trivial en comparación con la cantidad de tiempo de solución de problemas y el dinero que puede ahorrar teniendo toda la información que necesita ya disponible cuando algo va mal. Después, cuando alguien le dice que tenía un error aleatorio en algún momento alrededor de las 8:00 anoche, pero no recuerda el error, puede averiguar fácilmente cuál era el problema.

Para menos de 4 USD al mes, puede mantener 50 gigabytes de registros a mano y el impacto en el rendimiento del registro es trivial siempre que tenga en cuenta una cosa, con el fin de evitar cuellos de botella de rendimiento, asegúrese de que la biblioteca de registro es asincrónica.

Diferenciar los registros que informan de los registros que requieren acción

Los registros están diseñados para INFORM (quiero que sepa algo) o ACT (quiero que haga algo). Tenga cuidado de escribir solo registros ACT para los problemas que realmente requieren una persona o un proceso automatizado para tomar medidas. Demasiados registros ACT crearán ruido, lo que requiere demasiado trabajo para examinarlo todo para encontrar problemas genuinos. Y si los registros ACT desencadenan automáticamente alguna acción, como enviar correo electrónico al personal de soporte técnico, evite permitir que miles de acciones de este tipo se desencadenen mediante un único problema.

En el seguimiento de System.Diagnostics de .NET, se pueden asignar registros de nivel de error, advertencia, información y depuración o detallado. Puede diferenciar ACT de los registros INFORM reservando el nivel de error para los registros ACT y usando los niveles inferiores para los registros INFORM.

Logging levels

Configuración de los niveles de registro en tiempo de ejecución

Aunque merece la pena tener el registro siempre activado en producción, otro procedimiento recomendado es implementar un marco de registro que le permita ajustar en tiempo de ejecución el nivel de detalle que está registrando, sin volver a implementar ni reiniciar la aplicación. Por ejemplo, al usar la instalación de seguimiento en System.Diagnostics puede crear registros de error, advertencia, información y depuración o detallados. Se recomienda registrar siempre los registros de errores, advertencias e información en producción, y querrá poder agregar dinámicamente el registro de depuración o detallado para solucionar problemas de mayúsculas y minúsculas.

Web Apps en Azure App Service tiene compatibilidad integrada para escribir System.Diagnostics registros en el sistema de archivos, Table Storage o Blob Storage. Puede seleccionar distintos niveles de registro para cada destino de almacenamiento y puede cambiar el nivel de registro sobre la marcha sin reiniciar la aplicación. La compatibilidad con Blob Storage facilita la ejecución de trabajos de análisis de HDInsight en los registros de aplicación, ya que HDInsight sabe cómo trabajar directamente con Blob Storage.

para registrar excepciones

No solo pongas una excepción. ToString() en el código de registro. Eso deja información contextual. En el caso de errores de SQL, deja fuera el número de error de SQL. Para todas las excepciones, incluya información de contexto, la propia excepción y las excepciones internas para asegurarse de que proporciona todo lo necesario para solucionar problemas. Por ejemplo, la información de contexto podría incluir el nombre del servidor, un identificador de transacción y un nombre de usuario (pero no la contraseña ni ningún secreto).

Si confía en que cada desarrollador haga lo correcto con el registro de excepciones, algunos de ellos no lo harán. Para asegurarse de que se realiza de la manera correcta cada vez, cree el control de excepciones directamente en la interfaz del registrador: pase el propio objeto de excepción a la clase de registrador y registre los datos de excepción correctamente en la clase de registrador.

Registro de llamadas a servicios

Se recomienda encarecidamente escribir un registro cada vez que la aplicación llame a un servicio, ya sea en una base de datos o en una API REST o en cualquier servicio externo. Incluya en los registros no solo una indicación de éxito o error, sino cuánto tiempo tardó cada solicitud. En el entorno de nube, a menudo verá problemas relacionados con ralentizaciones en lugar de interrupciones completas. Algo que normalmente toma 10 milisegundos podría empezar a tomar un segundo de repente. Cuando alguien le indica que la aplicación es lenta, quiere poder examinar New Relic o cualquier servicio de telemetría que tenga y valide su experiencia y, después, desea poder ver son sus propios registros para profundizar en los detalles de por qué es lento.

Usar una interfaz ILogger

Lo que se recomienda hacer al crear una aplicación de producción es crear una interfaz ILogger sencilla y pegar algunos métodos en ella. Esto facilita el cambio de la implementación de registro más adelante y no tiene que pasar por todo el código para hacerlo. Podríamos usar la System.Diagnostics.Trace clase en toda la aplicación Fix It, pero en su lugar la usamos en segundo plano en una clase de registro que implementa ILogger y realizamos llamadas al método ILogger en toda la aplicación.

De este modo, si alguna vez desea que el registro sea más rico, puede reemplazar por System.Diagnostics.Trace el mecanismo de registro que desee. Por ejemplo, a medida que crece la aplicación, puede decidir que desea usar un paquete de registro más completo, como NLog o Bloque de aplicaciones de registro de bibliotecas empresariales. (Log4Net es otro marco de registro popular, pero no realiza el registro asincrónico).

Una posible razón para usar un marco como NLog es facilitar la división de la salida del registro en almacenes de datos de alto volumen y de alto valor independientes. Esto le ayuda a almacenar de forma eficaz grandes volúmenes de datos INFORM en los que no es necesario ejecutar consultas rápidas, al tiempo que mantiene el acceso rápido a los datos ACT.

Registro semántico

Para obtener una forma relativamente nueva de realizar el registro que puede generar información de diagnóstico más útil, vea Bloque de aplicación de registro semántico de biblioteca empresarial (SLAB). SLAB usa el seguimiento de eventos para Windows (ETW) y la compatibilidad con EventSource en .NET 4.5 para permitirle crear registros más estructurados y consultables. Defina un método diferente para cada tipo de evento que registre, lo que le permite personalizar la información que escribe. Por ejemplo, para registrar un error de SQL Database, podría llamar a un LogSQLDatabaseError método. Para ese tipo de excepción, sabe que un fragmento de información clave es el número de error, por lo que puede incluir un parámetro de número de error en la firma del método y registrar el número de error como un campo independiente en el registro que escriba. Dado que el número está en un campo independiente, puede obtener informes de forma más fácil y confiable en función de los números de error de SQL que podría si simplemente concatenó el número de error en una cadena de mensaje.

Iniciar sesión en la aplicación Fix It

La interfaz ILogger

Esta es la interfaz ILogger de la aplicación Fix It.

public interface ILogger
{
    void Information(string message);
    void Information(string fmt, params object[] vars);
    void Information(Exception exception, string fmt, params object[] vars);

    void Warning(string message);
    void Warning(string fmt, params object[] vars);
    void Warning(Exception exception, string fmt, params object[] vars);

    void Error(string message);
    void Error(string fmt, params object[] vars);
    void Error(Exception exception, string fmt, params object[] vars);

    void TraceApi(string componentName, string method, TimeSpan timespan);
    void TraceApi(string componentName, string method, TimeSpan timespan, string properties);
    void TraceApi(string componentName, string method, TimeSpan timespan, string fmt, params object[] vars);
}

Estos métodos permiten escribir registros en los mismos cuatro niveles admitidos por System.Diagnostics. Los métodos TraceApi son para registrar llamadas de servicio externos con información sobre la latencia. También puede agregar un conjunto de métodos para el nivel Debug/Verbose.

Implementación del registrador de la interfaz ILogger

La implementación de la interfaz es realmente sencilla. Básicamente, simplemente llama a los métodos estándarSystem.Diagnostics. En el fragmento de código siguiente se muestran los tres métodos information y uno de los demás.

public class Logger : ILogger
{
    public void Information(string message)
    {
        Trace.TraceInformation(message);
    }

    public void Information(string fmt, params object[] vars)
    {
        Trace.TraceInformation(fmt, vars);
    }

    public void Information(Exception exception, string fmt, params object[] vars)
    {
        var msg = String.Format(fmt, vars);
        Trace.TraceInformation(string.Format(fmt, vars) + ";Exception Details={0}", exception.ToString());
    }

    public void Warning(string message)
    {
        Trace.TraceWarning(message);
    }

    public void Error(string message)
    {
        Trace.TraceError(message);
    }

    public void TraceApi(string componentName, string method, TimeSpan timespan, string properties)
    {
        string message = String.Concat("component:", componentName, ";method:", method, ";timespan:", timespan.ToString(), ";properties:", properties);
        Trace.TraceInformation(message);
    }
}

Llamar a los métodos ILogger

Cada vez que el código de la aplicación Fix It detecta una excepción, llama a un método ILogger para registrar los detalles de la excepción. Y cada vez que realiza una llamada a la base de datos, Blob service o una API REST, inicia un cronómetro antes de la llamada, detiene el cronómetro cuando el servicio vuelve y registra el tiempo transcurrido junto con información sobre éxito o error.

Observe que el mensaje de registro incluye el nombre de clase y el nombre del método. Se recomienda asegurarse de que los mensajes de registro identifiquen qué parte del código de la aplicación los escribió.

public class FixItTaskRepository : IFixItTaskRepository
{
    private MyFixItContext db = new MyFixItContext();
    private ILogger log = null;

    public FixItTaskRepository(ILogger logger)
    {
        log = logger;
    }

    public async Task<FixItTask> FindTaskByIdAsync(int id)
    {
        FixItTask fixItTask = null;
        Stopwatch timespan = Stopwatch.StartNew();

        try
        {
            fixItTask = await db.FixItTasks.FindAsync(id);
            
            timespan.Stop();
            log.TraceApi("SQL Database", "FixItTaskRepository.FindTaskByIdAsync", timespan.Elapsed, "id={0}", id);
        }
        catch(Exception e)
        {
            log.Error(e, "Error in FixItTaskRepository.FindTaskByIdAsynx(id={0})", id);
        }

        return fixItTask;
    }

Por lo tanto, por cada vez que la aplicación Fix It ha realizado una llamada a SQL Database, puede ver la llamada, el método que lo llamó y exactamente cuánto tiempo tardó.

SQL Database query in logs

screenshot showing the Edit Entity Properties and what each property should look like for a successful update with how much time it took.

Si va a examinar los registros, puede ver que la hora en que tardan las llamadas a la base de datos es variable. Esa información podría ser útil: dado que la aplicación registra todo esto, puede analizar tendencias históricas en el rendimiento del servicio de base de datos a lo largo del tiempo. Por ejemplo, un servicio podría ser más rápido la mayor parte del tiempo, pero las solicitudes podrían producir errores o las respuestas podrían ralentizarse en determinados momentos del día.

Puede hacer lo mismo para Blob service: por cada vez que la aplicación carga un nuevo archivo, hay un registro y puede ver exactamente cuánto tiempo tardó en cargar cada archivo.

Blob upload log

Es solo un par de líneas de código adicionales para escribir cada vez que se llama a un servicio, y ahora cada vez que alguien dice que se produjo un problema, sabe exactamente cuál era el problema, ya sea un error o incluso si se estaba ejecutando lentamente. Puede identificar el origen del problema sin tener que realizar el control remoto en un servidor o activar el registro después de que se produzca el error y espere a volver a crearlo.

Demostración: Inserción de dependencias en la aplicación Fix it

Es posible que se pregunte cómo obtiene el constructor del repositorio en el ejemplo anterior la implementación de la interfaz del registrador:

public class FixItTaskRepository : IFixItTaskRepository
{
    private MyFixItContext db = new MyFixItContext();
    private ILogger log = null;

    public FixItTaskRepository(ILogger logger)
    {
        log = logger;
    }

Para conectar la interfaz a la implementación, la aplicación usa la inserciónde dependencias (DI) con AutoFac. La inserción de dependencias permite usar un objeto basado en una interfaz en muchos lugares en todo el código y solo tiene que especificar en un solo lugar la implementación que se usa cuando se crea una instancia de la interfaz. Esto facilita el cambio de la implementación: por ejemplo, es posible que quiera reemplazar el registrador System.Diagnostics por un registrador de NLog. O para las pruebas automatizadas, es posible que quiera sustituir una versión ficticia del registrador.

La aplicación Fix It usa di en todos los repositorios y en todos los controladores. Los constructores de las clases de controlador obtienen una interfaz ITaskRepository de la misma manera que el repositorio obtiene una interfaz de registrador:

public class DashboardController : Controller
{
    private IFixItTaskRepository fixItRepository = null;

    public DashboardController(IFixItTaskRepository repository)
    {
        fixItRepository = repository;
    }

La aplicación usa la biblioteca de di AutoFac para proporcionar automáticamente instancias TaskRepository y Logger para estos constructores.

public class DependenciesConfig
{
    public static void RegisterDependencies()
    {
        var builder = new ContainerBuilder();

        builder.RegisterControllers(typeof(MvcApplication).Assembly);
        builder.RegisterType<Logger>().As<ILogger>().SingleInstance();

        builder.RegisterType<FixItTaskRepository>().As<IFixItTaskRepository>();
        builder.RegisterType<PhotoService>().As<IPhotoService>().SingleInstance();
        builder.RegisterType<FixItQueueManager>().As<IFixItQueueManager>();

        var container = builder.Build();
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
    }
}

Este código básicamente dice que en cualquier lugar donde un constructor necesita una interfaz ILogger, pase una instancia de la clase Logger y siempre que necesite una interfaz IFixItTaskRepository, pase una instancia de la clase FixItTaskRepository.

AutoFac es uno de los muchos marcos de inserción de dependencias que puede usar. Otro popular es Unity, que es recomendado y compatible con patrones y prácticas de Microsoft.

Demostración: Compatibilidad con el registro integrado en Azure

Azure admite los siguientes tipos de registro para Web Apps en Azure App Service:

  • Seguimiento de System.Diagnostics (puede activar y desactivar y establecer niveles sobre la marcha sin reiniciar el sitio).
  • Eventos de Windows.
  • Registros de IIS (HTTP/FREB).

Azure admite los siguientes tipos de registro en Cloud Services:

  • System.Diagnostics.Tracing.
  • Contadores de rendimiento.
  • Eventos de Windows.
  • Registros de IIS (HTTP/FREB).
  • Supervisión de directorios personalizados.

La aplicación Fix It usa el seguimiento de System.Diagnostics. Todo lo que debe hacer para habilitar el registro de System.Diagnostics en una aplicación web es voltear un conmutador en el portal o llamar a la API REST. En el portal, haga clic en la pestaña Configuración del sitio y desplácese hacia abajo para ver la sección Diagnósticos de aplicaciones. Puede activar o desactivar el registro y seleccionar el nivel de registro que desee. Puede hacer que Azure escriba los registros en el sistema de archivos o en una cuenta de almacenamiento.

App diagnostics and site diagnostics in Configure tab

Después de habilitar el registro en Azure, puede ver los registros en la ventana Salida de Visual Studio a medida que se crean.

Streaming logs menu

Streaming logs menu2

También puede tener registros escritos en la cuenta de almacenamiento y verlos con cualquier herramienta que pueda acceder al servicio Azure Storage Table, como el Explorador de servidores en Visual Studio o el Explorador de Azure Storage.

Logs in Server Explorer

Resumen

Es realmente sencillo implementar un sistema de telemetría preconfigurado, el registro de instrumentos en su propio código y configurar el registro en Azure. Y cuando tenga problemas de producción, la combinación de un sistema de telemetría y registros personalizados le ayudará a resolver los problemas rápidamente antes de que se conviertan en problemas importantes para los clientes.

En el capítulo siguiente veremos cómo controlar los errores transitorios para que no se conviertan en problemas de producción que tenga que investigar.

Recursos

Para obtener más información, vea los recursos siguientes.

Documentación principalmente sobre telemetría:

Documentación principalmente sobre el registro:

Documentación principalmente sobre la solución de problemas:

Videos:

  • FailSafe: creación de servicios en la nube escalables y resistentes. Serie de nueve partes de Ulrich Homann, Marc Mercuri y Mark Simms. Presenta conceptos de alto nivel y principios arquitectónicos de una manera muy accesible e interesante, con historias extraídas de la experiencia del Equipo de asesoramiento al cliente (CAT) de Microsoft con clientes reales. Los episodios 4 y 9 se tratan sobre la supervisión y la telemetría. El episodio 9 incluye información general sobre los servicios de supervisión MetricsHub, AppDynamics, New Relic y PagerDuty.
  • Building Big: lecciones de los clientes de Azure: parte II. Mark Simms habla sobre el diseño de errores e instrumentación de todo. Similar a la serie Failsafe, pero se incluyen más detalles de procedimientos.

Ejemplo de código: