Registro y seguimiento en aplicaciones .NET
A medida que continúe desarrollando su aplicación y se haga más compleja, querrá aplicarle diagnósticos de depuración adicionales.
El seguimiento es una manera de monitorizar la ejecución de tu aplicación mientras está en funcionamiento. Puede agregar instrumentación de seguimiento y depuración a la aplicación .NET al desarrollarla. Además, puede usar esa instrumentación mientras desarrolla la aplicación y después de implementarla.
Esta técnica sencilla es sorprendentemente poderosa. Puede usarlo en situaciones en las que necesite algo más que un simple depurador.
- Los problemas que se producen durante largos períodos de tiempo pueden ser difíciles de depurar con un depurador tradicional. Los registros permiten una revisión post mortem detallada que abarca largos períodos de tiempo. Por el contrario, los depuradores están restringidos al análisis en tiempo real.
- Las aplicaciones multiproceso y las aplicaciones distribuidas suelen ser difíciles de depurar. La asociación de un depurador tiende a modificar comportamientos. Puede analizar registros detallados según lo necesite para comprender los sistemas complejos.
- Los problemas en las aplicaciones distribuidas pueden surgir de una interacción compleja entre muchos componentes. No suele ser recomendable conectar un depurador a todas las partes del sistema.
- Muchos servicios no deben estar detenidos. La asociación de un depurador suele provocar errores de tiempo de espera.
- Los problemas no siempre se prevén. El registro y el seguimiento están diseñados para una sobrecarga baja para que los programas siempre puedan grabarse en caso de que se produzca un problema.
Escritura de información en las ventanas de salida
Hasta este momento, hemos estado usando la consola para mostrar información al usuario de la aplicación. Hay otros tipos de aplicaciones creadas con .NET que tienen interfaces de usuario, como aplicaciones móviles, web y de escritorio, y no hay ninguna consola visible. En estas aplicaciones, System.Console registra los mensajes "en segundo plano". Estos mensajes pueden aparecer en una ventana de salida en Visual Studio o Visual Studio Code. También pueden generarse en un registro del sistema, como logcat de Android. Como resultado, se debe tener mucho cuidado al usar System.Console.WriteLine en una aplicación que no es de consola.
Aquí es donde puede usar System.Diagnostics.Debug y System.Diagnostics.Trace, además de System.Console. Tanto Debug como Trace forman parte de System.Diagnostics y solo escribirán en los registros cuando se asocie un agente de escucha adecuado.
La elección de la API de estilo de impresión que se va a usar es para usted. Las diferencias clave son:
- System.Console
- Siempre habilitado y siempre escribe en la consola.
- Resulta útil para la información que el cliente pueda necesitar ver en la versión.
- Dado que es el enfoque más sencillo, a menudo se usa para la depuración temporal ad hoc. Este código de depuración a menudo nunca se comprueba en el control de código fuente.
- System.Diagnostics.Trace
- Solo se habilita cuando
TRACEse define. - Escribe en los agentes de escucha asociados, de forma predeterminada, DefaultTraceListener.
- Use esta API cuando cree registros que se habilitarán en la mayoría de las compilaciones.
- Solo se habilita cuando
- System.Diagnostics.Debug
- Solo se habilita cuando se define
DEBUG(en modo de depuración). - Escribe en un depurador asociado.
- Use esta API cuando cree registros que solo se habilitarán en las compilaciones de depuración.
- Solo se habilita cuando se define
Console.WriteLine("This message is readable by the end user.");
Trace.WriteLine("This is a trace message when tracing the app.");
Debug.WriteLine("This is a debug message just for developers.");
Al diseñar su estrategia de seguimiento y depuración, piense en cómo quiere que sea la salida. Varias instrucciones Write rellenadas con información no relacionada crean un registro que es difícil de leer. Por otro lado, usar WriteLine para colocar instrucciones relacionadas en líneas independientes puede hacer que sea difícil distinguir la información del mismo tipo. En general, use varias instrucciones Write cuando quiera combinar información de varios orígenes para crear un único mensaje informativo. Por otro lado, use la instrucción WriteLine cuando quiera crear un único mensaje completo.
Debug.Write("Debug - ");
Debug.WriteLine("This is a full line.");
Debug.WriteLine("This is another full line.");
Esta salida proviene del registro anterior con Debug:
Debug - This is a full line.
This is another full line.
Definición de las constantes TRACE y DEBUG
De forma predeterminada, cuando una aplicación se ejecuta durante la depuración, se define la constante DEBUG. Para controlarlo, puede agregar una entrada DefineConstants al archivo de proyecto en un grupo de propiedades. Este es un ejemplo de cómo activar TRACE para las configuraciones de Debug y Release, además de DEBUG para las configuraciones de Debug.
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DefineConstants>DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DefineConstants>TRACE</DefineConstants>
</PropertyGroup>
Si usa Trace cuando no está asociado al depurador, deberá configurar un agente de escucha de seguimiento, como dotnet-trace.
Seguimiento condicional
Además de los métodos simples Write y WriteLine, también existe la funcionalidad para agregar condiciones con WriteIf y WriteLineIf. Por ejemplo, la siguiente lógica comprueba si el recuento es cero y, a continuación, escribe un mensaje de depuración:
if(count == 0)
{
Debug.WriteLine("The count is 0 and this may cause an exception.");
}
Puede volver a escribir esto en una sola línea de código:
Debug.WriteLineIf(count == 0, "The count is 0 and this may cause an exception.");
También puede usar estas condiciones con Trace y con las marcas que defina en la aplicación:
bool errorFlag = false;
System.Diagnostics.Trace.WriteIf(errorFlag, "Error in AppendData procedure.");
System.Diagnostics.Debug.WriteIf(errorFlag, "Transaction abandoned.");
System.Diagnostics.Trace.Write("Invalid value for data request");
Comprobación de que determinadas condiciones existen
Una aserción, o instrucción Assert, prueba una condición que usted especifica como argumento de la instrucción Assert. Si la condición se evalúa como true, no se produce ninguna acción. Si la condición se evalúa como false, se produce un error en la aserción. Si está ejecutando una compilación de depuración, el programa entra en modo de interrupción.
Puede usar el método Assert de Debug o Trace, que se encuentran en el espacio de nombres System.Diagnostics. Los métodos de la clase Debug no se incluyen en una versión de lanzamiento de su programa, de modo que no aumentan el tamaño ni reducen la velocidad de su código de versión.
Use el método libremente para probar las condiciones que deben contener true si el System.Diagnostics.Debug.Assert código es correcto. Por ejemplo, supongamos que ha escrito una función de división de enteros. Por las reglas de matemáticas, el divisor nunca puede ser cero. Puede probar esta condición mediante una aserción:
int IntegerDivide(int dividend, int divisor)
{
Debug.Assert(divisor != 0, $"{nameof(divisor)} is 0 and will cause an exception.");
return dividend / divisor;
}
Al ejecutar este código en el depurador, se evalúa la instrucción de aserción, Sin embargo, la comparación no se realiza en la versión de lanzamiento, por lo que no hay ninguna sobrecarga adicional.
Nota:
Cuando use System.Diagnostics.Debug.Assert, asegúrese de que cualquier código incluido en Assert no cambie los resultados del programa si se quita Assert. De lo contrario, podría introducir accidentalmente un error que solo se muestra en la versión de lanzamiento del programa. Tenga especial cuidado con las aserciones que contienen llamadas a funciones o procedimientos.
Usar Debug y Trace desde el System.Diagnostics espacio de nombres es una excelente manera de proporcionar contexto adicional al ejecutar y depurar la aplicación.