Mejores prácticas para iniciar sesión y rastrear en .NET

53

He estado leyendo mucho sobre el rastreo y el registro, tratando de encontrar alguna regla de oro para las mejores prácticas en la materia, pero no hay ninguna. La gente dice que los buenos programadores producen un buen seguimiento, pero lo expresan así y tiene que venir de la experiencia.

También he leído preguntas similares aquí y a través de Internet y en realidad no son lo mismo que pregunto o no tienen una respuesta satisfactoria, tal vez porque las preguntas carecen de algunos detalles.

Entonces, la gente dice que el rastreo debería replicar la experiencia de depurar la aplicación en los casos en que no se puede adjuntar un depurador. Debe proporcionar suficiente contexto para que pueda ver qué ruta se toma en cada punto de control de la aplicación.

Yendo más profundo, incluso puede distinguir entre el rastreo y el registro de eventos, ya que "el registro de eventos es diferente del rastreo, ya que captura los estados principales en lugar del flujo de control detallado".

Ahora, digamos que quiero hacer mi rastreo y registro usando solo las clases estándar de .NET, aquellas en el System.Diagnosticsespacio de nombres. Pensé que la clase TraceSource es mejor para el trabajo que la clase Trace estática, porque quiero diferenciar entre los niveles de rastreo y usar la clase TraceSource puedo pasar un parámetro que informe el tipo de evento, mientras que usando la clase Trace debo usar Trace.WriteLineIfy luego verifica cosas como SourceSwitch.TraceInformationy SourceSwitch.TraceErrors, y ni siquiera tiene propiedades como TraceVerboseo TraceStart.

Con todo eso en mente, ¿consideraría una buena práctica hacer lo siguiente?

  • Rastree un evento "Inicio" cuando comience un método, que debe representar una sola operación lógica o una tubería, junto con una representación en cadena de los valores de los parámetros pasados ​​al método.
  • Rastree un evento de "Información" al insertar un elemento en la base de datos.
  • Rastree un evento de "Información" al tomar una ruta u otra en una importante declaración if / else.
  • Rastree un "Crítico" o "Error" en un bloque catch dependiendo de si es un error recuperable.
  • Rastree un evento "Stop" cuando termine la ejecución del método.

Y también, aclare cuándo es mejor rastrear los tipos de eventos detallados y de advertencia. Si tiene ejemplos de código con buen seguimiento / registro y está dispuesto a compartir, sería excelente.

Nota: He encontrado buena información aquí, pero aún no es lo que estoy buscando: http://msdn.microsoft.com/en-us/magazine/ff714589.aspx

Levidad
fuente
tal vez la forma preferida de iniciar sesión en la red desplegada a azul en stackoverflow también sea útil.
k3b
¿alguna aplicación de muestra de código fuente completo que use buenos patrones para iniciar sesión?
Kiquenet
Honestamente ... Si estuviera trabajando con .NET, probablemente instalaría algo como New Relic y lo llamaría hecho. (Tal vez no sea una buena opción en el momento en que esto se publicó)
svidgen

Respuestas:

17

La importancia de los tipos de rastreo debe elegirse no por la ubicación del código, sino porque el mensaje rastreado es más o menos importante. Ejemplo:

Rastree un evento "Inicio" cuando comience un método, que debe representar una sola operación lógica o una tubería, junto con una representación en cadena de los valores de los parámetros pasados ​​al método.

Utilice el tipo de inicio cuando comience una operación lógica. Esto no significa que la traza de inicio debe estar al comienzo de un método, ni tampoco significa que un método debe tener una traza de inicio.

Dicho esto, en la mayoría de los casos, una operación lógica comenzará realmente al comienzo del método. De lo contrario, debe preguntarse si el código se refactorizó correctamente.

Los parámetros de rastreo también pueden ser una mala idea . Tienes que pensar qué rastrear, caso por caso. Por ejemplo, es realmente malo rastrear los parámetros de un método void Authenticate(string userName, string plainPassword).

Rastree un evento de "Información" al insertar un elemento en la base de datos.

Depende. Se deben rastrear algunos elementos, pero no todos.

  • Por ejemplo, imagine que en realidad está insertando un elemento de registro en su base de datos. ¿Trazarías los registros? ¿Y luego registrar los rastros? Y luego rastrear el registro de la traza?
  • Otro ejemplo: estás insertando datos confidenciales. Esto requiere auditoría. Desde que auditó la inserción, ¿por qué rastrearla?

Rastree un evento de "Información" al tomar una ruta u otra en una importante declaración if / else.

De nuevo, depende.

Rastree un "Crítico" o "Error" en un bloque de captura dependiendo del clima, este es un error recuperable.

La acción tomada después de un error no recuperable puede ser más que un seguimiento. Por ejemplo, en el lado del servidor, le gustaría almacenar la excepción en la base de datos para su posterior análisis. Además, algunas excepciones son menos importantes que otras y no requieren seguimiento.

Rastree un evento "Stop" cuando termine la ejecución del método.

Ver el primer punto.

por favor aclare cuándo es mejor rastrear tipos de eventos detallados y de advertencia.

Verboso:

Verbose se usa para rastrear lo que necesita rastrear cuando algo sale realmente mal. Significa que en la mayoría de los casos, deshabilitará el rastreo de mensajes detallados, pero a veces, debe depurar algunas partes de su código para comprender por qué algo falla en un caso límite.

Por lo general, tiene muchos mensajes detallados que le permiten comprender muy bien el flujo de la aplicación. También significa que esos mensajes deben deshabilitarse la mayor parte del tiempo porque:

  • de lo contrario, el registro crecerá muy rápido,
  • no los necesitas la mayor parte del tiempo,
  • pueden contener datos confidenciales sobre el flujo de la aplicación.

Piense en verbose como una herramienta que debe usar cuando no tiene acceso al depurador.

Advertencia:

El seguimiento de tipo de advertencia se usa cuando sucede algo incorrecto e importante, pero no es demasiado crucial para tratarlo como un error. Por ejemplo, la RAM baja puede emitir una advertencia, pero no hay ninguna razón para rastrear un error, ya que su aplicación puede continuar, incluso si será más lenta de lo habitual.

Ejemplos:

  • Ejemplo 1: la aplicación no pudo abrir el archivo que el usuario solicitó abrir. El archivo existe y no está en uso, los permisos están configurados correctamente, pero algo bloquea la apertura de un archivo. En este caso, rastreará un error , ya que su aplicación no puede gestionar este caso y continuará funcionando según lo esperado por el usuario (es decir, leer el archivo).

  • Ejemplo 2: después de la inspección del error en el primer ejemplo, encuentra que el error es causado por el hecho de que la ruta del archivo tiene más de 259 caracteres. Entonces refactorizas tu código para atraparlo PathTooLongException. Cuando, la próxima vez, el usuario intente abrir el mismo archivo, la nueva versión de la aplicación muestra un mensaje que explica que el archivo es demasiado largo y debe moverse a otra carpeta para acortar la ruta completa para abrir este archivo en esta aplicación. También trazas un mensaje .

  • Ejemplo 3: su aplicación pasó veinte segundos abriendo y analizando un archivo pequeño, mientras que la mayoría de los archivos tardan entre diez y cien milisegundos en abrirse y analizarse. Puede rastrear una advertencia con información relevante: el tipo de disco donde se encuentra realmente el archivo, el sistema de archivos, el tamaño del archivo, el tiempo exacto empleado, el tiempo que estuvo encendida la computadora, etc. Cuando el usuario se queja de que toma veinte segundos para abrir el archivo, toma el rastro para encontrar lo que sucede. Usted encuentra, por ejemplo, que toma mucho tiempo cargar los archivos desde un recurso compartido de red cuando la computadora acaba de comenzar. Le explica al usuario que la demora se debe a la red y no está relacionada con su aplicación.

  • Ejemplo 4: el archivo abierto se muestra incorrectamente. Habilita el rastreo detallado donde realmente ve cómo se cargan los datos del archivo y luego se analiza, paso a paso.

Arseni Mourzenko
fuente
Un patrón que utilizamos donde trabajo es registrar "KnownErrors" como advertencias y "UnknownErrors" como errores. Puede no ser apropiado dependiendo de su infraestructura y de cómo maneja las advertencias, pero funciona bien para nosotros.
Andrew Piliser
5
 > say I want to do my tracing and logging using only the standard .NET classes

System.Diagnostics es excelente porque puede configurar dónde debe ir la información de rastreo (archivo, registro de eventos, base de datos, ...)

Desafortunadamente, si desea usar System.Diagnosticsdebe saber de antemano ( en el momento designado ), qué secuencias de seguimiento deben ser posibles de seguir. (En el artículo de ejemplo, estos son Transferir, Reanudar, Suspender, ...). Estos se pueden configurar para ser deshabilitado, nivel de depuración o nivel de error.

Prefiero tener un sistema de registro donde pueda decidir en tiempo de ejecución sobre classlevel / namespacelevel , qué tan detallado debe ser el registro. Por ejemplo, todos Debug y superior desde MyNamespace.Business.*pero no MyNamespace.Business.Calculations.

Si está utilizando log4net (o Common.logging), cada clase tiene su propio registrador para que pueda decidir fácilmente qué clases se registran en qué nivel.

Dado que las operaciones de la base de datos están en una clase separada, ya no hay necesidad de una regla distinta

Trace an "Information" event when inserting an item into the database.

En cambio, prefiero tener estas pautas:

  • Tracelevel debería mostrar el flujo de trabajo básico
  • Debuglevel debe mostrar datos detallados y procesamiento dentro del flujo de trabajo, incluidas las decisiones en el flujo de programa con razones (Creación de un nuevo elemento porque el elemento no existía en la base de datos)
  • Nivel de información para iniciar / detener servicios y una entrada para cada acción de flujo de trabajo / GUI iniciada
k3b
fuente
Ya veo, esa es buena información, gracias! Pero aún así, como hago en mi pregunta original, ¿podría aclarar los usos de los tipos de evento Verbose y Warning? Y también, le pido a otras personas que contribuyan con su punto de vista, porque este tema merece una exploración más profunda de lo que he visto en Internet.
Levidad
4

Puede probar el marco de Story , tiene un enfoque único para iniciar sesión, ya que "hace" que escriba todos los registros (y agregue otra información relevante) en contexto, de modo que cuando necesite leerlo más tarde obtenga todo lo que necesita.

Agregará automáticamente los conceptos de "inicio" y "detención" como el principio y el final de una historia.

Y con un sistema basado en reglas, puede controlar qué hacer con cada historia (contexto) en función de la información que tiene, por ejemplo, imprimir todas las historias que tienen un error o provienen del usuario "administrador".

También más información sobre esta publicación de blog

Amit Apple
fuente
1
respuesta actualizada con más información
Amit Apple