Diagnóstico de nube

Tome el control de registro y seguimiento en Windows Azure

Mike Kelly

Descargar el ejemplo de código

Como muchos programadores, cuando comencé a escribir código por primera vez, utilicé instrucciones print para depuración. No sabía como usar un depurador y las instrucciones print eran una manera rudimentaria pero eficiente para ver lo que mi programa estaba haciendo al ser ejecutado. Después, aprendí a usar un verdadero depurador y eliminé las instrucciones print como una herramienta de depuración.

Avancemos hasta cuando comencé a escribir código que se ejecuta en servidores. Me di cuenta que aquellas instrucciones print se encuentran ahora entre las tendencias más sofisticadas de técnicas esenciales de “registro y seguimiento” para cualquier programador de aplicaciones de servidores.

Aún si se pudiera adjuntar un depurador a una aplicación de un servidor de producción, lo que a menudo no es posible debido a las restricciones de seguridad en las máquinas que hospedan la aplicación, los tipos de problemas que se derivan de las aplicaciones de servidores no se revelan fácilmente con los depuradores tradicionales. Muchas aplicaciones de servidores se distribuyen, ejecutándose en varias máquinas, y depurar lo que está pasando en una máquina no siempre es suficiente para diagnosticar los problemas del mundo real.

Además de eso, las aplicaciones de servidores a menudo se ejecutan bajo el control de un equipo de operaciones que no sabría utilizar un depurador tradicional, y llamar al desarrollador para cada problema no es deseable ni práctico.

En este artículo, explicaré algunas técnicas básicas de registro, seguimiento y depuración usadas para aplicaciones de servidores. Después, profundizaremos sobre cómo se pueden emplear esas técnicas para sus proyectos de Windows Azure. A lo largo del artículo veremos cómo se usa el registro y el seguimiento con algunas aplicaciones reales, y le mostraremos cómo usar Windows PowerShell para administrar el diagnóstico para un servicio en ejecución.

Una estrategia de registro

Idealmente, cualquier aplicación de servidor, y básicamente cualquier aplicación web, incluidas aquellas que se ejecutan bajo Windows Azure, tiene una estrategia de registro y seguimiento diseñada desde el principio. La información de registro debe ser lo suficientemente sólida para describir casi todo lo que está pasando dentro de cada componente. Sin embargo, tal como aquellas instrucciones print que agregué a mis primeros programas podían producir muchos resultados, también se pueden registrar. Un registro y seguimiento bien diseñado incluye así maneras de ajustar el tipo y el volumen de registro de cualquier componente. Esto permite que el equipo de operaciones y los desarrolladores se centren en un determinado componente con un comportamiento inadecuado, tal vez incluso en una determinada máquina, para obtener mucha más información sobre lo que está sucediendo exactamente dentro de esta, sin generar demasiado ruido en el registro que pudiera ser distractivo y tal vez ralentizar significativamente la aplicación.

Además, ya que las aplicaciones normalmente son aplicaciones distribuidas, la información se debe recolectar y agregar desde varias máquinas (tal vez en diferentes roles de aplicación) para tener una idea completa de lo que estaba sucediendo cuando ocurrió un problema determinado. Así, es importante tener una manera de identificar un subproceso de transacción a través de las máquinas, permitiendo la agregación después del hecho.

El registro disponible en Windows Azure ha madurado a través de las versiones del Community Technology Preview (CTP). Los primeros registros no eran mucho más sofisticados que una instrucción print, capturada como texto en el almacenamiento de tablas de Windows Azure. Empezando con la versión PDC09, Windows Azure comenzó a ofrecer una infraestructura de registro y seguimiento mucho más completa, basada en el marco de Seguimiento de eventos para Windows (ETW).

Este marco ETW es compatible con ASP.NET por medio de clases en el espacio de nombres en System.Diagnostics. El espacio de nombres de Microsoft.WindowsAzure.Diagnostics, que se hereda y se extiende de las clases estándar System.Diagnostics, permite el uso de System.Diagnostics como un marco de registro en el entorno Windows Azure. La figura 1 muestra cómo ETW es implementado por Windows Azure Diagnostics.

Figure 1 High-Level Overview of Windows Azure Diagnostics
Figura 1 Descripción general de alto nivel de Windows Azure Diagnostics

ETW proporciona un modelo en el cual los códigos registran a uno o más TraceSources. El nivel de registro permitido por medio de cada origen es controlado por SourceSwitch. Las fuentes están conectadas por su parte a uno o más consumidores, que mantienen la información de registro de diferentes maneras.

Windows Azure proporciona un consumidor estándar o agente de escucha para mantener la información de registro generada, ya sea en almacenamiento de tablas o almacenamiento de blob de Windows Azure. También puede escribir su propio consumidor si desea hacer algo diferente con los datos de evento, o usar un consumidor ya existente (aunque algunos se deben modificar para trabajar en el entorno de Windows Azure).

El marco ETW asocia un TraceEventType con cada evento, como se muestra en la figura 2. Las cinco primeras filas de valores de gravedad son los valores más comunes usados e indican la importancia relativa de los resultados del seguimiento. Observe que los tipos Suspend, Resume y Transfer son usados por Windows Communication Foundation (WCF).

Figura 2 Tipos de evento de seguimiento

TraceEventType Valor Significado
Crítico 0x0001 Error grave o bloqueo de aplicación
Error 0x0002 Error recuperable
Advertencia 0x0004 Problema no crítico, puede ser una indicación de que vienen problemas más serios
Información 0x0008 Mensaje informativo
Detallado 0x0010 Seguimiento de depuración (tal como información de flujo de ejecución detallada, parámetros, etc.)
Inicio 0x0100 Inicio de una operación lógica
Detener 0x0200 Detención de una operación lógica
Suspender 0x0400 Suspensión de una operación lógica
Reanudar 0x0800 Reanudación de una operación lógica
Transferir 0x1000 Transferir a una nueva actividad

Si está buscando sólo cosas realmente malas, deseará estar seguro para capturar valores Críticos y probablemente de Error. Si desea mucha información sobre lo que está pasando, mire todo lo que está antes de Detallado.

Su estrategia de registro debe incluir el uso consistente del tipo de evento y abundantes entradas de registro con los valores más abajo de la jerarquía. Puede ser posible seguir virtualmente el flujo de ejecución de su aplicación si se está habilitado el registro para todos los valores destacados en su aplicación. Esto puede ser inestimable en la solución de problemas de un error o problema en producción.

Puede asociar agentes de escucha, orígenes y conectores para permitir la habilitación de diferentes niveles de resultados de una manera programática, pero esto se hace normalmente por medio de archivos de configuración. Puede configurar los resultados en app.config (para las funciones de trabajador de Windows Azure) o web.config (para las funciones web de Windows Azure). Sin embargo, como se explicará de manera detallada más adelante en el artículo, colocar esto en ServiceConfiguration.cscfg le permite ajustar las opciones de registro y seguimiento mientras el servicio Windows Azure se está ejecutando, sin tener que desplegar nuevamente cualquier actualización al código de ejecución o siquiera detener el servicio. Windows Azure también expone una interfaz RESTful para permitir el control sobre algunas opciones de registro de manera remota. Windows PowerShell puede usar la interfaz RESTful.

Resultados de registro, seguimiento y depuración

Los términos de resultados de registro, seguimiento y depuración se pueden usar a veces de manera intercambiable. En este artículo, se distinguirá entre cuatro tipos diferentes de lo que de una manera general se puede llamar diagnosticoutput en su código. Están ordenados más o menos desde el más detallado al menos detallado.

  • Resultado de depuración: esta es una información que sólo aparece en la creación de depuración de su aplicación y se excluye en el momento de la compilación de la construcción de lanzamiento (basado en si el símbolo del preprocesador de DEBUG se define en el momento de la compilación, que Visual Studio define de manera predeterminada sólo en las construcciones de depuración). Normalmente, los resultados de la depuración incluyen cosas como aserciones que le agrega para ayudar a encontrar casos donde el código no cumple con las condiciones previamente esperadas, llevando a errores, o incluso a volcados de la estructura de datos. Agregando esas ayudas puede depurar algoritmos durante la depuración y prueba.
  • Seguimiento: estas son instrucciones que tienen la intención de ayudar a rastrear el flujo de control y estado del programa mientras se está ejecutando. Imagine que está ejecutando un depurador, paso a paso a lo largo del código y comprobando los valores de variables clave en la ventana de Inspección. Las instrucciones de seguimiento están destinadas a replicar esa experiencia en casos donde no puede adjuntar un depurador. Estas deberían proporcionar idealmente un contexto suficiente para poder ver qué ruta se ha tomado en cada punto de control de la aplicación y seguir más o menos el código desde la lectura de las instrucciones de rastreo. El seguimiento se habilita cuando el símbolo del preprocesador TRACE se define en tiempo de compilación, y puede estar tanto en versiones de depuración como de lanzamiento. (Visual Studio define TRACE de manera predeterminada tanto en versiones de depuración como de lanzamiento, pero claramente esto se puede cambiar).
  • Registro de eventos: son instrucciones destinadas a capturar eventos importantes en el curso de la ejecución de la aplicación, por ejemplo, el inicio de una transacción o al agregar un elemento a la base de datos. El registro de evento es diferente del seguimiento en el que captura estados importantes en vez de un flujo de control detallado.
  • Registro de errores: estos son casos especiales de registro de eventos en los cuales puede capturar situaciones excepcionales o potencialmente peligrosas. Ejemplos de esto incluyen cualquier excepción detectada; casos donde no puede tener acceso a un recurso en otra máquina en la que se esperaba tener posibilidad de acceso (y en la que, por supuesto, su aplicación controlará correctamente pero desearía señalar); y casos donde los errores vienen desde API desde las que no se esperan errores.

El registro de errores también puede ser útil al equipo de operaciones en situaciones donde los problemas aún no están ocurriendo, pero hay indicaciones de que pronto lo harán, por ejemplo, una cuota que está cerca de su máximo o una transacción que está teniendo éxito pero que toma más tiempo de lo usual. Estos tipos de eventos de registros pueden ayudar al equipo de operaciones a abordar problemas de una manera proactiva antes de que ocurran, evitando un tiempo de inactividad de la aplicación.

La mayoría de los buenos desarrolladores los han usado para incluir resultados de depuración en sus aplicaciones para ayudarlos a diagnosticar problemas durante el desarrollo, y muchos han desarrollado algún tipo de solución para registro de errores.

Sin embargo, necesita estar seguro de que no está considerando solamente las opciones de resultados de depuración y de registro de errores, sino que también tiene una sólida estrategia para seguimiento y registro de eventos, que pueden ayudar realmente a diagnosticar problemas que ocurren sólo bajo cargas muy exigentes en los entornos de producción.

Considere cuidadosamente también si mucho de lo que piensa ahora como un resultado de depuración no debiera ser trazado y estar disponible tanto en las versiones de depuración como de lanzamiento. Una aplicación en producción con un comportamiento inadecuado estará normalmente ejecutando la versión de lanzamiento. Si las instrucciones de seguimiento están presentes pero deshabilitadas (como se explicará más adelante), puede habilitarlas selectivamente para obtener resultados del tipo de depuración de la versión de lanzamiento, para ayudarlo con los problemas de diagnóstico.

Seguimiento y registro en Windows Azure

Puede usar el registro de Windows Azure que está listo para usar, puesto que es parte de Windows Azure SDK. Existen algunas ventajas para usar un marco de registro como Logger.NET, Enterprise Library, log4net o Ukadc.Diagnostics. Estos agregan una estructura adicional a sus mensajes de registro y también ayudan a entregar algo de la capacidad de configuración antes mencionada. Sin embargo, la mayoría no se han modificado para trabajar en el entorno Windows Azure y algunos son mucho más que un marco de registro.

Para el código de ejemplo de este artículo, decidí usar sólo las API estándar de registro y seguimiento de Windows Azure con una delgada capa superior para entregar una configuración dinámica. Probablemente encontrará que es útil crear algunas clases auxiliares y un marco para su estrategia de registro y seguimiento por encima de esto, o ver otros marcos para proveer versiones de Windows Azure.

Cuando crea un servicio nuevo en Windows Azure usando Visual Studio, ya está habilitado para hacer el registro básico. El código de modelo Worker Role y Web Role generado por las plantillas de Windows Azure tiene los agentes de escucha de diagnóstico ya configurados y habilitados.

Para habilitar un registro sencillo en un servicio de Windows Azure, comience un nuevo proyecto en Visual Studio usando la plantilla (Visual C#) de servicio de nube de Windows Azure. Asigne un nombre al proyecto. Para mi ejemplo usé MSDNSampleLoggingService. Haga clic en Aceptar.

Se ejecutará el asistente de nuevo proyecto de servicio de nube. En el asistente, agregue un Worker Role y un Web Role al proyecto. Cambie el nombre de Worker Role a LoggingWorkerRole y el de Web Role a LoggingWebRole, después haga clic en Aceptar. Visual Studio creará el proyecto.

En este momento, puede explorar el código generado. Mire en app.config en el proyecto LoggingWorkerRole y observe que aparece el siguiente código:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.diagnostics>
    <trace autoflush="false" indentsize="4">
      <listeners>
        <add name="AzureDiagnostics" type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Mi-crosoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
      </listeners>
    </trace>
  </system.diagnostics>
</configuration>

Esto enlaza el agente de escucha de diagnóstico estándar de Windows Azure a su código, lo que significa que cualquier registro y seguimiento que haga desde el rol de trabajo será dirigido al agente de escucha de Windows Azure (DiagnosticMonitorTraceListener) a menos que cambie esto. Encontrará una entrada similar en web.config para el Web Role creado para este servicio.

Si observa el archivo WorkerRole.cs file en el proyecto del rol de trabajo , también verá esta línea en el método OnStart:

DiagnosticMonitor.Start("DiagnosticsConnectionString");

Y en el método Run, verá una llamada para seguimiento:

// This is a sample worker implementation. Replace with your logic.
Trace.WriteLine("LoggingWorkerRole entry point called", "Information");

Finalmente, si mira en el archivo ServiceConfiguration.cscfg en la raíz Service, verá esta línea tanto para Worker Role como para Web Role:

<Setting name="DiagnosticsConnectionString" 
         value="UseDevelopmentStorage=true" />

Esto le dice al escucha de Windows Azure qué cuenta de almacenamiento usar para conservar la información de registro y seguimiento. En este caso, la información de registro se almacenará en el almacenamiento de desarrollo en su máquina local. Al cambiar esto a una cuenta de almacenamiento en nube de Windows Azure, puede hacer que los registros se vayan a un almacenamiento en nube. Aquí hay un ejemplo del formato para eso del código de ejemplo proporcionado con este artículo:

<Setting name="DiagnosticsConnectionString" 
  value="DefaultEndpointsProtocol=https;AccountName=Xxxxxx;AccountKey=Yyyyyy" />

Los valores AccountName y AccountKey se deben personalizar con sus datos de cuenta y clave de Azure. Puede obtener esta información en el portal de cuentas de almacenamiento para su servicio en windows.azure.com. AccountName es la primera parte de la dirección URL para los extremos de almacenamiento de tabla y blob (la parte antes de “.table.core.windows.net”). AccountKey es la clave de acceso principal codificada Base 64 para su cuenta de almacenamiento.

Observe que, como existe una cuenta de almacenamiento diferente que se usa para información de diagnósticos, puede escoger almacenar su información de diagnósticos de forma separada de sus otros datos de aplicación. Para hacerlo, configure una cuenta separada de almacenamiento haciendo clic en Servicio nuevo en la página del portal, seleccionando Cuenta de almacenamiento y dándole un nombre (por ejemplo, MyAppLogs). Puede desear configurar un grupo de afinidad para que el almacenamiento de sus registros esté en la misma región que su servicio.

Ahora que ha tenido un repaso rápido sobre el código de seguimiento en los servicios de Windows Azure, puede ejecutar el sencillo proyecto Web Role que ha creado. Observe que el agente de escucha predeterminado que proporciona Windows Azure también dirige los resultados a la ventana Resultados en Visual Studio para las versiones de depuración, por lo que verá aparecer el mensaje OnStart en la ventana de depuración:

Information: LoggingWorkerRole entry point called

¿Qué ocurre si desea ver los registros después de la ejecución del servicio? Windows Azure no mantiene los registros para almacenar de manera predeterminada. Puede decirle que haga esto agregando algunas líneas de código al método OnStart de su rol:

TimeSpan tsOneMinute = TimeSpan.FromMinutes(1);
DiagnosticMonitorConfiguration dmc =
DiagnosticMonitor.GetDefaultInitialConfiguration();

// Transfer logs to storage every minute
dmc.Logs.ScheduledTransferPeriod = tsOneMinute;
// Transfer verbose, critical, etc. logs
dmc.Logs.ScheduledTransferLogLevelFilter = LogLevel.Verbose;    
// Start up the diagnostic manager with the given configuration
DiagnosticMonitor.Start("DiagnosticsConnectionString", dmc);

Agregar este código a WorkerRole.cs y ejecutarlo de nuevo, hará que Windows Azure transfiera los registros al almacenamiento de desarrollo a cada minuto. También puede elegir hacer una transferencia de registros a petición (vea el código en admin.aspx.cs en mi aplicación de ejemplo para saber cómo hacer esto) o use los comandos de Windows PowerShell descritos más adelante en este artículo. Recuerde que una vez que transfiere los registros al almacenamiento, se le cobrará por el espacio de almacenamiento y depende de usted eliminar la información cuando no sea más necesaria.

Una vez que tiene los registros en el almacenamiento de Windows Azure, necesitará una herramienta para ver las tablas de almacenamiento a fin de ver los registros. Yo usé Estudio de almacenamiento en nube de Cerebrata (cerebrata.com). Cerebrata viene con una herramienta llamada Administrador de diagnósticos de Azure, y también hay herramientas gratis disponibles en CodePlex (codeplex.com) para observar almacenamientos de nube y diagnósticos. Los registros se colocan en una tabla llamada WADLogsTable, que se puede ver en la figura 3.

Figure 3 Logs Persisted in Development Storage
Figura 3 Registros que se mantienen en almacenamiento de desarrollo

Observará un par de cosas cuando vea los registros en almacenamiento. En primer lugar, Windows Azure asocia automáticamente algunas informaciones con cada evento registrado: una marca de tempo, un recuento de marca (que entrega una temporización más detallada con una granularidad de 100 nanosegundos), e información sobre la implementación, rol e instancia de rol. Esto le permite limitar los registros a instancias específicas que desea.

En segundo lugar, hay un Level y un EventId asociado con cada evento. El nivel corresponde a los valores en la figura 2, aquellos eventos en seguimiento registrados como información tendrán un valor de nivel de 4, mientras que aquellos registrados como error tendrán un nivel de 2. Los eventos genéricos enviados a través de Trace.WriteLine (como lo hace el código modelo) tendrán un nivel 5 (detallado).

EventId es un valor que usted especifica. La llamada básica Trace.WriteLine mostrada antes no le permite especificarlo; tiene que usar otros métodos de Rastreo para pasar el EventId.

Habilitación selectiva de seguimiento y registro

Una aplicación típica consiste en varios componentes lógicos. Por ejemplo, puede tener un componente de base de datos que trata con el modelo de datos en el almacenamiento de Windows Azure. Su Web Role puede a su vez ser dividido en un componente administrativo y en un componente de usuario (y además estos se pueden dividir en componentes lógicos basados en las necesidades de su aplicación).

Puede enlazar las opciones de registro y seguimiento, qué tipo de registro se habilita y a qué nivel de detalles, a esos componentes. Esto permite que habilite el seguimiento selectivamente sólo en los componentes para los que lo necesitan, evitando mucho desorden.

Aquí el enfoque clave es no llamar directamente a Trace, sino usar múltiples instancias de TraceSource, normalmente una por espacio de nombre. Un TraceSource tiene un SourceSwitch asociado que controla si el origen está habilitado, así como cuál es el nivel de resultados deseado. De una manera importante, los valores SourceSwitch no se configuran en tiempo de compilación, sino en tiempo de ejecución. Como resultado, puede habilitar o deshabilitar los resultados de diagnóstico desde varias partes de su aplicación sin tener que compilarlas nuevamente, o siquiera implementar de nuevo una versión diferente.

WorkerDiagnostics.cs y WebDiagnostics.cs contienen la configuración de los orígenes de seguimiento y conmutadores en el código de ejemplo. Aquí se muestra un extracto:

// Trace sources
public TraceSource ConfigTrace;
public TraceSource WorkerTrace;
// Add additional sources here

// Corresponding trace switches to control 
// level of output for each source
public SourceSwitch ConfigTraceSwitch { get; set; }
public SourceSwitch WorkerTraceSwitch { get; set; }
// Add additional switches 1:1 with trace sources here

Entonces, en el archivo de configuración para su rol, enlaza esos agentes de escucha como se muestra en la figura 4. Esto configura los agentes de escucha de diagnóstico estándar de Windows Azure como agentes de escucha compartidos, por lo que se puede hacer referencia a estos en los elementos <sources>. Esto entonces configura dos orígenes: un origen WorkerTrace y un origen ConfigTrace. También configura los conmutadores correspondientes para permitirle ajustar el nivel de resultados. ConfigTrace le entrega la salida más detallada; WorkerTrace sólo le entrega errores.

Figura 4 Configuración de orígenes de seguimiento y agentes de escucha

<configuration>
  <system.diagnostics>
    <sharedListeners>
      <add type="Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        name="AzureDiagnostics">
        <filter type="" />
      </add>
    </sharedListeners>
    <sources>
      <source name="ConfigTrace">
        <listeners>
          <add name="AzureDiagnostics" />
        </listeners>
      </source>
      <source name="WorkerTrace">
        <listeners>
          <add name="AzureDiagnostics" />
        </listeners>
      </source>
    </sources>
    <switches>
      <add name="ConfigTrace" value="Verbose"/>
      <add name="WorkerTrace" value="Error"/>
    </switches>
    <trace>
      <listeners>
        <add name="AzureDiagnostics" />
      </listeners>
    </trace>
  </system.diagnostics>
</configuration>

No tiene que nombrar a los conmutadores igual que a los orígenes, pero hacerlo simplifica la vida. Si no son las mismas, agrega un atributo switchName al elemento de origen para indicar el nombre del conmutador que controla los resultados para este origen. Esto permite que comparta un solo conmutador con varios orígenes de seguimiento. Observe que los nombres del origen de seguimiento y del conmutador distinguen entre mayúsculas y minúsculas y deben coincidir exactamente con la que pasa al constructor en su código.

Puede evitar completamente el conmutador si lo desea simplemente agregando un atributo switchValue al elemento de origen especificando el valor de conmutador deseado para este origen. Los valores de conmutador que usa en realidad se analizan desde el archivo de configuración como uno de los SourceLevels definidos en la figura 5, que muestran también como el TraceEventType que pasa a las llamadas TraceSource interactúa con el conjunto de SourceLevel para el origen a fin de determinar lo que pasa a través de él.

Figura 5 Niveles de seguimiento de origen y TraceEventType

Figure 5 Tracing Source Levels and TraceEventType

Puede haberse dado cuenta que SourceLevel sólo es una máscara de bits que es ANDed en tiempo de ejecución con TraceEventType para determinar si se registra el evento. Para obtener combinaciones como advertencia y actividad de seguimiento, especifique el valor numérico para el campo de bits como el valor de conmutador en vez de usar los valores simbólicos que se muestran.

Además de conmutadores, un agente de escucha puede tener un TraceFilter, que agrega lógica en tiempo de ejecución más sofisticada respecto de si se permite un mensaje determinado. Escribir un TraceFilter personalizado está más allá del ámbito de este artículo, pero encontrará un ejemplo útil en la documentación de proyecto de Ukadc.Diagnostics en CodePlex (ukadcdiagnostics.codeplex.com/wikipage?title=LoggingPrimer).

Cambio de lo registrado en tiempo de ejecución

Esta es la manera predeterminada en que trabaja el seguimiento de ASP.NET y trabajará bien con los servicios implementados para Windows Azure. El problema es que le gustaría poder cambiar los valores en el tiempo de ejecución, y Windows Azure no le permite cambiar solamente web.config o app.config sin reimplementar el servicio. La solución genérica ASP.NET para esto es usar WebConfiguationManager para alterar los valores de configuración, pero Windows Azure tampoco permite actualmente hacerlo para los servicios implementados en nube.

La solución es reflejar los valores para esos conmutadores en ServiceConfiguration.cscfg. Windows Azure le permite editar ese archivo (o cargar uno nuevo) a través del portal de desarrollo mientras su servicio se está ejecutando. Sin embargo. deberá escribir algo de código adicional para hacer este trabajo.

El código predeterminado System.Diagnostics tiene toda la información de configuración sólo en app.config o web.config, pero sus roles obtendrán la notificación de cambios de tiempo de ejecución en ServiceConfiguration.cscfg por medio de los eventos RoleEnvironmentChanging y RoleEnvironmentChanged. Puede decidir entonces si reciclar (reiniciar) el rol o simplemente actualizar un valor de configuración. La última opción es la que desea para conmutadores de seguimiento. Reiniciar el rol puede hacer desaparecer los problemas intermitentes. El código de ejemplo para este artículo muestra cómo hacer esto agregando un par de valores al ServiceConfiguration.cscfg (observe que también tiene que editar ServiceDefinition.csdef, que proporciona el esquema) y agregar algo de código a sus roles.

Prueba del entramado de desarrollo

¿Qué hay sobre probar el entramado de desarrollo, donde no tiene el portal Windows Azure para editar la configuración como lo hace para los servicios implementados en nube? En primer lugar, determine el identificador de implementación que Windows Azure ha asignado a su servicio de ejecución de entramado de desarrollo. Puede hacer esto mostrando la UI del entramado de desarrollo desde la bandeja del sistema mientras el servicio se está ejecutando. Será un número como 177.

  1. Vaya al directorio donde la compilación colocó sus binarios de servicio, normalmente \bin\debug o \bin\release bajo su código de servicio. Encontrará la copia de ServiceConfiguration.cscfg que se creó cuando compiló la aplicación.
  2. En seguida, usando un editor de texto, edite este archivo para usar el conmutador de seguimiento que desee. Por ejemplo, en el código de ejemplo, cambie WebTrace de Off a Verbose (Detallado).
  3. Lo siguiente es, en un indicador de símbolo de sistema Windows Azure SDK (Inicio | Todos los programas | Windows Azure SDK v1.1 | Windows Azure SDK Command Prompt), ejecute este comando:
csrun /update:NNN;ServiceConfiguration.cscfg

NNN es el identificador de implementación de Windows Azure que encontró anteriormente. Esto hará en el entramado de desarrollo lo que hace el portal de desarrollo de Windows Azure al hacer clic en el botón Configurar para los servicios implementados en nube: actualizar la configuración y desencadenar los eventos.

Otras informaciones de diagnóstico

Mientras que este artículo se ha centrado en datos tabulares que su aplicación registra usando System.Diagnostics, Windows Azure también puede capturar registros IIS y registros de seguimiento de solicitudes con error (antes conocidas como almacenamiento en búfer de solicitudes con error, o FREB), entre otros. Algunos de estos están en el almacenamiento en blob de Windows Azure, algunos en el almacenamiento de tablas de Windows Azure. La figura 6 lista los registros disponibles y el lugar donde están almacenados. Observe que para esos que no están habilitados de manera predeterminada, normalmente debe hacer un cambio en web.config o app.config para que Windows Azure recopile esos registros. Examinemos un ejemplo no recopilado de manera predeterminada para mostrar cómo funciona esto.  

Figura 6 Opciones de registro estándar de Azure

Tipo de registro Formato de almacenamiento de Windows Azure ¿Recopilados de manera predeterminada? Notas
Registros de Windows Azure generados a partir de su código Tabla 4 Se debe agregar un agente de escucha de seguimiento al archivo web.config o app.config como se muestra en el código de ejemplo. Almacenado en WADLogsTable.
Registros IIS 7.0 Blob 4 Sólo roles web. Almacenado en un contenedor de blob bajo la ruta wad-iis-logfiles\<deployment ID>\<web role name>\<role instance>\W3SVC1.
Registros de infraestructura de diagnóstico de Windows Tabla 4 Información sobre el servicio de diagnóstico mismo. Almacenado en WADDiagnosticInfrastructureLogsTable.
Registros de solicitud con error Blob   Sólo roles web. Habilitado al definir opciones de seguimiento en la configuración de system.WebServer en web.config. Almacenado en un contenedor de blob bajo la ruta wad-iis-failedreqlogfiles\<deployment ID>\<web role name>\<role instance>\W3SVC1.
Registros de eventos de Windows Tabla   Habilitado al alterar DiagnosticMonitor Configuration.WindowsEventLog en el momento de establecer la configuración inicial. Almacenado en WADWindowsEventLogsTable. El blog de Steve Marx (blog.smarx.com/posts/capturing-filtered-windows-events-with-windows-azure-diagnostics) explica cómo usar esto.
Contadores de rendimiento Tabla   Habilitado al alterar la configuración de DiagnosticMonitor. PerformanceCounters. Almacenado en WADPerformanceCountersTable. El rol de trabajo del código de ejemplo establece un contador de rendimiento.
Volcados Blob   Habilitar mediante una llamada a CrashDumps.EnableCollection. Almacenado en un contenedor de blob bajo la ruta wad-crash-dumps. Como ASP.NET administra la mayoría de las excepciones , esto es generalmente útil para el rol de trabajo.
Registros de error personalizados Blob   Está más allá del ámbito de este artículo, pero consulte el blog de Neil Mackenzie (nmackenzie.spaces.live.com/blog/cns!B863FF075995D18A!537.entry) para ver un ejemplo útil sobre cómo usar esto.

Como un ejemplo, veamos cómo habilitar FREB registrándose desde IIS en su rol de trabajo. Para ver esto en acción, descargue el código de ejemplo para MSDNSampleLoggingService proporcionado con este artículo. Abra web.config para el LoggingWebRole y encuentre la sección etiquetada <system.webServer>. Observe que las líneas que se muestran en la figura 7 se han agregado a web.config predeterminado de Windows Azure. Esto resulta en un registro de error para cualquier solicitud que tome más de 15 segundos o con los códigos de estado entre 400 y 599 (el elemento failureDefinitions).

Figura 7 Registro de solicitud con error para LoggingWebRole

<tracing>
  <traceFailedRequests>
    <add path="*">
      <traceAreas>
        <add provider="ASP" verbosity="Verbose" />
        <add provider="ASPNET" 
             areas="Infrastructure,Module,Page,AppServices"
             verbosity="Verbose" />
        <add provider="ISAPI Extension" verbosity="Verbose" />
        <add provider="WWW Server"
             areas="Authentication,Security,Filter,StaticFile,CGI,Compression,Cache,RequestNotifications,Module" 
             verbosity="Verbose" />
      </traceAreas>
      <failureDefinitions timeTaken="00:00:15" statusCodes="400-599" />
    </add>
  </traceFailedRequests>
</tracing>

Si abre about.aspx.cs en el proyecto LoggingWebRole, observará que en el método PageLoad se agregó un retraso arbitrario de 18 segundos con esta línea de código:

System.Threading.Thread.Sleep(18000);

Esto forzará que la carga de esta página sea considerada una solicitud con error bajo la definición antes especificada.

Para ver el registro FREB, reconstruya e implemente la aplicación dentro del entramado de desarrollo y después encuentre el controlador del entramado de desarrollo en el área de notificación de la barra de tareas (puede tener que hacer clic en el botón Mostrar iconos ocultos en la barra de tareas, porque a menudo está oculto e inactivo). Haga clic con el botón secundario y seleccione la UI Mostrar el entramado de desarrollo. Mientras su aplicación se está ejecutando, esto mostrará información sobre la aplicación.

Amplíe el Web Role y haga clic con el botón secundario en la instancia de rol (0). Seleccione Abrir almacenamiento local para abrir la carpeta en la máquina local donde se están almacenando los registros (consulte la figura 8). Dentro de esa carpeta, los registros están en la carpeta \directory\DiagnosticStore. Esto es porque Web Role en el código de ejemplo está configurado para almacenar información de diagnóstico en el almacenamiento de desarrollo. Si en vez de eso define DiagnosticsConnectionString en una cuenta de almacenamiento en nube, los registros que se conservan estarán en el almacenamiento de blob asociados con esa cuenta de almacenamiento. Puede usar Estudio de almacenamiento en nube para ver los contenedores de almacenamiento de blob a fin de ver los registros.

Figure 8 Opening Logs Saved to Local Development Fabric Storage
Figura 8 Apertura de registros guardados en el almacenamiento del entramado de desarrollo local

Administración de diagnósticos para un servicio en ejecución

Aunque puede instrumentar profundamente su código con registros, normalmente no deseará toda la información que se mantiene en almacenamiento mientras su servicio de producción se está ejecutando. Puede desear sólo información de error y crítica para ir a los registros conservados, mientras que una información más detallada se suprime (registrada como Verbose o Information).

¿Pero qué pasa si ocurre un problema? No desea volver a implementar una nueva versión de su servicio o el problema podría desaparecer mágicamente, probablemente sabe lo eficiente que puede ser el reinicio para hacer desaparecer problemas evasivos.

En vez de eso, es más eficiente aumentar la cantidad de información que va a las tablas de registro o al almacenamiento de blob mientras que permite que un código con un comportamiento errático continúe ejecutándose. Esto es más o menos como revelar la causa del problema en su aplicación mientras está ejecutándose.

Anteriormente describí cómo afinar los detalles sobre qué registros pasan a los diagnósticos de Windows Azure para un determinado TraceSource. Eso es una especie de edición precedente sobre qué información se mantiene en registro. En esta sección, mostraré las configuraciones de diagnóstico generales de Windows Azure que determinan cómo la información que pasa a través de un TraceSource se mantiene en el almacenamiento.

Los cmdlets de Windows PowerShell pueden administrar muchos aspectos de sus servicios Windows Azure en ejecución, incluidos los diagnósticos. Usted los ejecuta desde su máquina local y se conectan a través de Internet a los servidores de nube de Windows Azure que ejecutan su servicio, entregando información y ajustando parámetros. Windows PowerShell se instala con Windows 7 y se puede descargar para Windows Vista desde microsoft.com/powershell. Descargue los cmdlets de administración de servicio de Windows Azure Service en code.msdn.microsoft.com/azurecmdlets y siga las instrucciones para instalarlos. Los comandos de Windows Azure relacionados con diagnósticos se muestran en la figura 9.

Figura 9 Cmdlets de diagnósticos de administración de Windows Azure

Nombre Descripción
Get-ActiveTransfers Devuelve el conjunto de transferencias de diagnóstico activas con la información de transferencia asociada.
Get-CommonConfigurationLogs Obtiene los valores de configuración comunes para todos los búferes de registro. Esto incluye el intervalo de tiempo en el que los cambios en la configuración se sondean y el tamaño del búfer asignado para esto en los registros en memoria.
Get-DiagnosticAwareRoleInstances Devuelve una lista de identificadores de instancias de roles activas que tienen un monitor de diagnóstico en ejecución.
Get-DiagnosticAwareRoles Lista el conjunto de roles que han iniciado correctamente al menos un monitor de diagnóstico.
Get-DiagnosticConfiguration Obtiene la configuración de búfer para el nombre especificado de búfer (Logs, Directories, PerformanceCounters, WindowsEventLogs or DiagnosticInfrastructureLogs).
Set-CommonConfigurationLogs Establece los valores de configuración comunes para todos los búferes de registro.
Set-FileBasedLog Establece la configuración de búfer para los registros basados en archivos.
Set-InfrastructureLog Establece la configuración de búfer para los registros generados por la infraestructura de diagnóstico subyacente de Windows Azure. Los registros de infraestructura de diagnóstico son útiles para solucionar problemas del mismo sistema de diagnóstico.
Set-PerformanceCounter Establece la configuración de búfer para los datos del contador de rendimiento que están siendo recopilados por su servicio.
Set-WindowsAzureLog Establece la configuración de búfer para los registros básicos de Windows Azure que están siendo generados por su servicio.
Set-WindowsEventLog Establece la configuración de búfer para los registros de eventos de Windows que están siendo generados por su servicio.
Start-OnDemandTransfer Comienza una transferencia a petición del búfer de datos especificado. Esto mueve los datos al almacenamiento de Windows Azure (sea en tablas o en almacenamiento de blob).
Stop-ActiveTransfer Detiene la transferencia activa a petición, dado un identificador de transferencia.

Por ejemplo, para encontrar los parámetros de transferencia actuales para una determinada instancia de rol, entregue el identificador de implementación (desde el portal del desarrollador de Windows Azure donde implementó el servicio) y la clave y nombre de la cuenta de almacenamiento que usó para DiagnosticsConnectionString en app.config o web.config para el rol de servicio (ver la figura 10). Observe que los indicadores de Windows PowerShell solicitan un par de parámetros que faltan, la instancia de rol y el nombre de búfer que desea. Logs se refiere a los registros estándar de Windows Azure. El resultado muestra que el nivel de filtro es Verbose (Detallado) y que una transferencia está programada a cada minuto.

Figure 10 Diagnostics Configuration for a Running Service Using Windows PowerShell
Figura 10 Configuración de diagnósticos para un servicio en ejecución mediante el uso de Windows PowerShell

Para cambiar la configuración para este rol, use el cmdlet Set-DiagnosticConfiguration, como se muestra en la figura 11. Observe que cambié el período de transferencia de un minuto a dos minutos y el filtro desde Verbose a Error, lo que significa que sólo los eventos registrados como Error y Críticos se enviarán y se mantendrán en el almacenamiento.

Figure 11 Changing Diagnostics Configuration from Windows PowerShell
Figura 11 Cambio de configuración de diagnósticos desde Windows PowerShell

Tal vez la cosa más útil que puede hacer de manera remota desde Windows PowerShell es forzar a una transferencia de información de registro inmediatamente. La figura 12 muestra cómo hacer eso.

Figure 12 Using Windows PowerShell to Initiate a Transfer of IIS Logs
Figura 12 Uso de Windows PowerShell para comenzar una transferencia de registros IIS

En primer lugar, pregunto por cualquier petición de transferencia de registros existente. Existe una restricción en la implementación de los diagnósticos actuales de Windows Azure que permite que sólo una petición de transferencia de un determinado tipo pueda ocurrir a la vez. Viendo que nada está en curso, pido una, pasando el identificador de implementación del servicio, el rol y la instancia, el tipo de registro que deseo transferir y el intervalo de tiempo de cada transferencia de datos. (Para el tipo de registro, Directories significa registros basados en archivos, incluyendo los registros IIS. Logs serían los registros de Windows Azure basados en tablas enviados a través de TraceSource).

También transmito un nombre de cola de notificaciones, que es donde los diagnósticos de Windows Azure enviarán una notificación avisando que la transferencia está completa. A través de la experimentación, encontré que si no transmitía una cola de notificación, la transferencia parecía no ocurrir. Obtengo un GUID identificando la solicitud de transferencia. Después consulto por el estado de la solicitud y veo que está publicada, lo que significa que está en curso.

La versión actual de los cmdlets de administración de servicio de Windows Azure parece no mostrar cuando la solicitud ya está completa, pero si consulta el almacenamiento de blob para su almacenamiento de diagnósticos verá luego los registros emergentes en la jerarquía de Contenedores (o en el almacenamiento de tabla de Windows Azure si pidió una transferencia de información almacenada en almacenamiento de tabla).

Conclusión

Mediante el uso una combinación de parámetros de configuración de ajuste para los TraceSources que definió en su código y usando los cmdlets de administración de servicio de Windows Azure para mover la información dentro del almacenamiento que se conserva, debería tener la posibilidad de controlar completamente qué resultado de diagnóstico obtiene de sus servicios Windows Azure.

Por supuesto, lo más importante que puede hacer para solucionar los problemas en el código de producción es desarrollar una sólida estrategia para tener resultados de diagnóstico en una etapa temprana del desarrollo, y después seguir esa estrategia a lo largo de toda la codificación. El uso de los TraceSources y las herramientas que entrega Windows Azure para configurar el nivel de detalle de los resultados de diagnóstico que fluyen desde su aplicación al almacenamiento le ayudará a tener acceso para obtener sólo la cantidad de información que necesita cuando surge un problema.

No hay nada peor que sentir que el código que se comporta de una manera errática en un servidor es una caja negra, poco clara para usted Un código de diagnósticos sólido y las herramientas aquí descritas lo dejarán abrir las tapas de esa caja y ver lo que ocurre dentro.  

Mike Kelly  es un consultor especializado en desarrollo de software y ayuda a integrar adquisiciones a grandes empresas. Trabajó anteriormente durante 15 años en Microsoft en muchas funciones de desarrollo de productos y como director de Prácticas emergentes en el equipo de Excelencia de ingeniería. Puede ponerse en contacto con él en himself@mikekellyconsulting.com.

Gracias a los siguientes expertos técnicos por la revisión de este artículo:  Sumit Mehrotra, Michael Levin y Matthew Kerner de Microsoft, así como Neil Mackenzie y Steven Nagy