urls tesis template sobre investigaciones example logging

logging - template - tesis sobre netflix



¿Cuál es su filosofía de registro? (12)

Como Jeff Atwood preguntó : "¿Cuál es su filosofía de registro? ¿Debería todo el código estar plagado de .logthis() y .logthat() llamadas? ¿O se inyectan registros después del hecho de alguna manera?"


Creo que siempre, siempre, siempre agregue el registro cuando hay una excepción, incluido el mensaje y el seguimiento completo de la pila. Más allá de eso, creo que es bastante subjetivo si usas o no los registros a menudo o no ...

A menudo trato de agregar solo el registro en lugares críticos en los que lo que estoy registrando rara vez aparece; de ​​lo contrario, obtienes el problema como él mencionó de los registros que crecen demasiado ... esto es por lo que el registro de errores es lo ideal para siempre log (y es genial poder ver cuándo se están dando estos casos de error para que pueda inspeccionar el problema aún más).

Otras cosas buenas para iniciar sesión son si tiene aserciones, y sus aserciones fallan, luego inicie sesión ... por ejemplo, esta consulta debe tener menos de 10 resultados; si es más grande, puede haber un problema, así que inicie sesión. Por supuesto, si una declaración de registro termina llenando los registros, es probable que sea una pista para ponerlo en algún tipo de nivel de "depuración", o para ajustar o eliminar la declaración de registro. Si los registros crecen demasiado, a menudo terminará ignorándolos.


Elijo registrarme deliberadamente sobre la marcha, ya que esto significa que los datos de registro son significativos:

  • Según el marco de trabajo de registro, puede agregar información de nivel / gravedad / categoría para que los datos de registro se puedan filtrar
  • Puede asegurarse de que el nivel correcto de información esté presente, no demasiado, no muy poco
  • Cuando escribes el código, sabes cuáles son las cosas más importantes y, por lo tanto, puedes asegurarte de que estén registradas

El uso de alguna forma de inyección de código, perfilado o herramienta de seguimiento para generar registros probablemente generaría registros detallados y menos útiles en los que sería más difícil profundizar. Sin embargo, pueden ser útiles como una herramienta de depuración.


Empiezo por afirmar muchas condiciones en mi código (en C #, usando System.Diagnostics.Assert ), pero agrego el registro solo donde encuentro, mientras depuro o pongo el sistema bajo tensión, que realmente necesito tener un camino para seguir lo que está sucediendo dentro de mi código sin tener un depurador conectado permanentemente.

De lo contrario, prefiero usar la capacidad de Visual Studio para poner rastros en el código como puntos de interrupción especiales (es decir, insertar un punto de interrupción y hacer clic derecho, luego seleccionar "Cuando golpear ..." y decirle qué mostrar en ese caso). No es necesario volver a compilar y es fácil activar / desactivar las huellas sobre la marcha.


Estoy de acuerdo con Adam, pero también consideraría registrar cosas de interés o cosas que pueda demostrar como logros como una especie de prueba de que están sucediendo.


Si está escribiendo un programa que será utilizado por muchas personas, es mejor tener algún tipo de mecanismo para elegir qué se registrará y qué no. Un argumento a favor de las funciones de .logthis () es que pueden ser un excelente reemplazo para los comentarios en línea en algunos casos (si se realizan correctamente).

Además, te ayuda a reducir EXACTAMENTE donde ocurre un error.


Tomo lo que considero un enfoque tradicional; algunos registros, rodeados de definiciones condicionales. Para construcciones de producción, apago las definiciones.


Conéctalos a todos y deja que Grep los clasifique.


Defino una variedad de niveles y paso en una configuración con la configuración / invocación.


Si realmente necesita iniciar sesión en su sistema, entonces sus pruebas son basura o al menos incompletas y poco exhaustivas. Todo en su sistema debe ser una caja negra tanto como sea posible. Observe cómo las clases básicas como String no necesitan registro, la razón principal es que están muy bien probadas y funcionan como se detalla. No hay sorpresas.


Mi filosofía de registro se resume fácilmente en cuatro partes:

Registro de auditoría o lógica de negocios

Registre las cosas que se requieren para ser registradas. Esto proviene de los requisitos de la aplicación y puede incluir registrar cada cambio realizado en cualquier base de datos (como en muchas aplicaciones financieras) o acceder a los datos de registro (como puede ser necesario en la industria de la salud para cumplir con las regulaciones de la industria)

Como esto es parte de los requisitos del programa, muchos no lo incluyen en sus discusiones generales sobre el registro, sin embargo, hay superposición en estas áreas, y para algunas aplicaciones es útil considerar todas las actividades de registro juntas.

Registro de programa

Mensajes que ayudarán a los desarrolladores a probar y depurar la aplicación, y seguir más fácilmente el flujo de datos y la lógica del programa para comprender dónde pueden existir implementación, integración y otros errores.

En general, este registro se activa y desactiva según sea necesario para las sesiones de depuración.

Registro de rendimiento

Agregue el registro posterior según sea necesario para encontrar y resolver los cuellos de botella de rendimiento y otros problemas del programa que no están causando el error del programa, pero que conducirán a un mejor funcionamiento. Se superpone con el registro de programa en el caso de pérdidas de memoria y algunos errores no críticos.

Registro de seguridad

Registro de acciones de usuario e interacciones con sistemas externos donde la seguridad es una preocupación. Útil para determinar cómo un atacante rompió un sistema después de un ataque, pero también puede unirse a un sistema de detección de intrusos para detectar ataques nuevos o en curso.


Trabajo con sistemas críticos de seguridad en tiempo real y el registro es a menudo la única forma de detectar errores raros que solo aparecen cada martes 53 cuando es luna llena, si entiendes mi deriva. Esto te hace obsesivo sobre el tema, así que me disculparé ahora si empiezo a sentir espuma en la boca.

Diseño sistemas que son capaces de registrar prácticamente todo, pero no enciendo todo de manera predeterminada. La información de depuración se envía a un diálogo de depuración oculto que marca el tiempo y lo envía a un cuadro de lista (limitado a alrededor de 500 líneas antes del borrado) y el diálogo me permite detenerlo, guardarlo automáticamente en un archivo de registro o desviarlo a un depurador adjunto como DBWin32. Esa desviación me permite ver la salida de depuración de múltiples aplicaciones, todas seriamente serializadas, lo que a veces puede ser un salvavidas. Los archivos de registro se purgan automáticamente cada N días. Solía usar niveles de registro numéricos (cuanto más alto estableces el nivel, más capturas):

  • apagado
  • solo errores
  • BASIC
  • detallado
  • todo

pero esto es demasiado inflexible: a medida que avanzas hacia un error, es mucho más eficiente poder enfocar el inicio de sesión exactamente en lo que necesitas sin tener que pasar por toneladas de detritus, y puede ser un tipo particular de transacción u operación eso causa el error Si eso requiere que enciendas todo, solo estás haciendo tu propio trabajo más duro. Necesitas algo más fino.

Así que ahora estoy en el proceso de cambiar a un registro basado en un sistema de banderas. Todo lo que se registra tiene una bandera que detalla qué tipo de operación es, y hay un conjunto de casillas de verificación que me permiten definir lo que se registra. Por lo general, esa lista se ve así:

#define DEBUG_ERROR 1 #define DEBUG_BASIC 2 #define DEBUG_DETAIL 4 #define DEBUG_MSG_BASIC 8 #define DEBUG_MSG_POLL 16 #define DEBUG_MSG_STATUS 32 #define DEBUG_METRICS 64 #define DEBUG_EXCEPTION 128 #define DEBUG_STATE_CHANGE 256 #define DEBUG_DB_READ 512 #define DEBUG_DB_WRITE 1024 #define DEBUG_SQL_TEXT 2048 #define DEBUG_MSG_CONTENTS 4096

Este sistema de registro se envía con la compilación de lanzamiento, se enciende y guarda en el archivo de forma predeterminada. Es demasiado tarde para descubrir que debería haber iniciado sesión DESPUÉS de que se haya producido el error, si ese error solo ocurre una vez cada seis meses en promedio y no tiene forma de reproducirlo.

El software generalmente se envía con ERROR, BASIC, STATE_CHANGE y EXCEPTION activados, pero esto se puede cambiar en el campo a través del diálogo de depuración (o una configuración de registro / ini / cfg, donde se guardan estos elementos).

Ah, y una cosa: mi sistema de depuración genera un archivo por día. Sus requisitos pueden ser diferentes. Pero asegúrese de que su código de depuración inicie cada archivo con la fecha, la versión del código que está ejecutando y, si es posible, algún marcador para la ID del cliente, la ubicación del sistema o lo que sea. Puede obtener una mezcla de archivos de registro que llegan del campo, y necesita algún registro de lo que vino de dónde y qué versión del sistema estaban ejecutando que está realmente en los datos en sí, y no puede confiar en el cliente / Ingeniero de campo para decirle qué versión tienen: pueden simplemente decirle qué versión PIENSA que tienen. Peor aún, pueden informar de la versión exe que está en el disco, pero la versión anterior sigue ejecutándose porque olvidaron reiniciarse después de reemplazarla. Haga que su código se lo diga a sí mismo.

Ese es mi cerebro abandonado ...


Utilizo el registro como una forma de reducir los problemas que no se reproducen en nuestras pruebas unitarias y mucho menos repetir los mismos pasos proporcionados por el usuario: esos problemas técnicos raros que solo aparecen en hardware muy remoto (y, a veces, aunque muy raramente, incluso causado por un error de la biblioteca del controlador o de un tercero fuera de nuestro control).

Estoy de acuerdo con el comentario de que todo esto debe ser atrapado por nuestro procedimiento de prueba, pero es difícil encontrar un millón de código de base LOC que exija un código de bajo nivel y rendimiento crítico para cumplir esos requisitos. No trabajo en software de misión crítica, pero trabajo en la industria de los gráficos donde a menudo tenemos que hacer todo, desde la implementación de asignadores de memoria hasta la utilización de códigos GPU a SIMD.

Incluso con un código muy modular, ligeramente acoplado o incluso completamente desacoplado, las interacciones del sistema pueden conducir a entradas y salidas muy complejas, con un comportamiento que varía entre las plataformas, donde ocasionalmente tenemos ese caso desviado que elude nuestras pruebas. Las cajas negras modulares pueden ser muy simples, pero las interacciones entre ellas pueden ser muy complejas y dar lugar a casos puntuales e imprevistos.

Como ejemplo de un caso donde el registro me salvó el trasero, una vez tuve este extraño usuario con un prototipo de máquina Intel que estaba fallando. Hemos enumerado los requisitos mínimos para las máquinas que deberían admitir SSE 4, pero esta máquina en particular cumplía con esos requisitos mínimos y aún no era compatible con Streaming SIMD extensiones más allá de SSE 3 a pesar de ser una máquina de 16 núcleos. Descubrir eso rápidamente fue posible al mirar su registro que mostraba precisamente el número de línea donde se usaron las instrucciones de SSE 4. Ninguno de nosotros en nuestro equipo pudo reproducir el problema, mucho menos un solo usuario que participó en la verificación del informe. Idealmente deberíamos haber escrito el código para versiones SIMD más antiguas o al menos hacer algunas ramificaciones y comprobaciones para asegurarnos de que el hardware soportara los requisitos mínimos, pero queríamos hacer una suposición firme comunicada a través de los requisitos mínimos de hardware por simplicidad y economía. Aquí, quizás, es discutible que fueran nuestros requisitos mínimos del sistema los que tenían el "error".

Dada la forma en que uso el registro aquí, tendemos a obtener registros bastante grandes. Sin embargo, el objetivo no es la legibilidad: lo que normalmente es importante es la última línea de un registro enviado con un informe cuando el usuario experimenta un bloqueo de algún tipo que ninguno de nosotros en el equipo (y mucho menos otros usuarios en el mundo) puede reproducirse

Sin embargo, un truco que empleo regularmente para evitar el spam excesivo es que a menudo es razonable suponer que una parte del código que se ejecuta una vez con éxito también lo hará posteriormente (no es una garantía dura, pero a menudo es una suposición razonable). Por lo tanto, a menudo log_once un tipo de función log_once para funciones granulares para evitar la sobrecarga de pagar el costo de iniciar sesión cada vez que se llama.

No rocío salidas de registro por todos lados (podría hacerlo si tuviera tiempo). Normalmente los reservo para las áreas que parecen ser las más peligrosas: código que invoca sombreadores GLSL, p. Ej. (Los proveedores de GPU varían enormemente aquí en términos de capacidad e incluso cómo compilan el código), código que usa intrínsecos SIMD, código de muy bajo nivel, código que inevitablemente tiene que depender del comportamiento específico del sistema operativo, suposiciones de bajo nivel sobre la representación de los POD (por ejemplo, código que asume 8 bits en un byte), el tipo de casos en los que también se rocían muchas aserciones y controles de cordura, así como escribir la mayor cantidad de pruebas unitarias. Normalmente, esto es suficiente, y el registro me ha salvado muchas veces de lo contrario de lo contrario hubiera tenido un problema irreproducible y habría tenido que apuñalar ciegamente el problema, requiriendo muchas iteraciones rebotando intentos de solución para el único usuario en el mundo que podría reproducir el problema