logging coding-style

logging - ¿Cobertura de código a registro?



coding-style (14)

También en estos días de poderosos IDE y depuración remota, ¿es mucho lo que se hace realmente?

Sí, absolutamente, aunque el error que muchos desarrolladores no calificados cometen es tratar de corregir errores utilizando el método incorrecto, por lo general tendiendo hacia el registro cuando deberían estar depurando. Hay un lugar para cada uno, pero hay al menos algunas áreas donde la tala casi siempre será necesaria:

  • Para examinar problemas en código en tiempo real, donde pausar con el depurador afectaría el resultado del cálculo (concedido, el registro tendrá un ligero impacto en el tiempo en un proceso en tiempo real como este, pero cuánto depende en gran medida del software)
  • Para compilaciones enviadas a beta testers u otros colegas que pueden no tener acceso a un depurador
  • Para volcar datos en el disco que pueden no ser fáciles de ver dentro de un depurador. Por ejemplo, ciertos IDE que no pueden analizar correctamente las estructuras de STL.
  • Para obtener una "sensación" del flujo normal de su programa
  • Para hacer que el código sea más legible además de los comentarios, haga lo siguiente:

// Now open the data file fp = fopen("data.bin", "rb");

El comentario anterior podría colocarse tan fácilmente en una llamada de registro:

const char *kDataFile = "data.bin"; log("Now opening the data file %s", kDataFile); fp = fopen(kDataFile, "rb");

Dicho eso, de alguna manera eres correcto. El uso del mecanismo de registro como un registrador de seguimiento de pila glorificado generará archivos de registro de muy mala calidad, ya que no proporciona un punto de falla suficientemente útil para que el desarrollador lo examine. Así que la clave aquí es, obviamente, el uso correcto y prudente de las llamadas de registro, que creo se reduce a la discreción del desarrollador. Debes considerar que esencialmente estás creando los archivos de registro por ti mismo ; sus usuarios no se preocupan por ellos y generalmente malinterpretarán groseramente sus contenidos de todos modos, pero puede usarlos para determinar al menos por qué su programa se comportó mal.

Además, es bastante raro que un archivo de registro lo señale a la fuente directa de un determinado error. En mi experiencia, por lo general proporciona una idea de cómo se puede replicar un error, y luego, ya sea por el proceso de replicación o depuración, encuentra la causa del problema.

¿Cuál es el código ideal para la tasa de registro? No estoy acostumbrado a escribir registros porque la mayoría de las aplicaciones que he desarrollado no han tenido mucho registro.

Recientemente, aunque cambié de trabajo, me di cuenta de que no puedes ver el código de la aplicación para las llamadas a log4net. Aprecio que esto sea útil, pero seguramente tener demasiadas declaraciones de depuración es tan malo como no tener ninguna.

Hay instrucciones de registro que le indican cuándo comienza y finaliza cada método y qué devuelve. y cuando casi todo está hecho.

¿No sería más fácil tener algún complemento que utilizara la reflexión para agregar las instrucciones de inicio de sesión en el momento de la compilación para que no se interpusieran en el camino mientras trataba de ver el código?

También en estos días de poderosos IDE y depuración remota, ¿es mucho lo que se hace realmente?


¿Cuántas de esas líneas están registrando por defecto? Trabajé en un sistema muy parecido a lo que describes: si lo iniciaste, se generarían más de 20 MB de registros si el inicio de sesión se hubiera acelerado, pero incluso la depuración no se completó en todos los módulos. . De forma predeterminada, se registraría cuando se ingresara un módulo de código y los principales eventos del sistema. Fue genial para la depuración ya que QA solo podía adjuntar un registro a un ticket, e incluso si no era reproducible, se podía ver lo que estaba sucediendo cuando ocurrió el problema. Si tienes problemas de subprocesos múltiples, el registro es mejor que cualquier otro IDE o depurador con el que haya trabajado.


Creo que "la relación de logs a código" es un malentendido del problema.

En mi trabajo, de vez en cuando tengo una situación en la que un error en un programa Java no se puede reproducir fuera del entorno de producción y donde el cliente NO quiere que vuelva a suceder.

Entonces, TODO lo que tiene disponible para corregir el error es la información que usted mismo ha puesto en los archivos de registro. Sin sesiones de depuración (lo que está prohibido en los entornos de producción de todos modos) - sin atornillar datos de entrada - ¡nada!

Entonces, los registros vuelven a su máquina del tiempo cuando ocurrió el error, y como no puede predecir con anticipación qué información necesitará para corregir un error aún desconocido, de lo contrario podría solucionar el error en primer lugar, debe iniciar sesión. un montón de cosas...

Exactamente QUÉ cosas depende del escenario, pero básicamente lo suficiente como para asegurarse de que nunca tenga dudas sobre qué sucede donde :)

Naturalmente, esto significa que habrá MUCHA tala. A continuación, creará dos registros: uno con todo lo que solo se mantiene durante el tiempo suficiente para garantizar que no lo necesitará, y el otro con información no trivial que se puede conservar durante mucho más tiempo.

Descartar el registro como excesivo, por lo general lo hacen aquellos que no han tenido que arreglar un error con nada más para hacerlo :)


Creo que otro factor es el conjunto de herramientas / plataforma que se utiliza y las convenciones que vienen con él. Por ejemplo, el registro parece ser bastante generalizado en el mundo J (2) EE, mientras que no recuerdo haber escrito nunca una declaración de registro en una aplicación Ruby on Rails.


Cuando se encuentra con un error durante la versión beta de su aplicación y no puede reproducirlo, sabe que debería haber realizado un registro excesivo. Del mismo modo si un cliente informa un error pero no puede reproducirlo, una función de registro excesiva puede salvar el día.


Cuando tiene un escenario de cliente (es decir, alguien cuya máquina no tiene acceso físico), las únicas cosas que son "demasiados registros" son las funciones de repintado y casi cualquier cosa que ellos llamen (que debería ser casi nada). O bien, otras funciones que se llaman 100 veces por segundo durante la operación (el inicio del programa está bien, sin embargo, tener cientos de llamadas para obtener / establecer rutinas registradas porque, en mi experiencia, ahí es donde se originan la mayoría de los problemas).

De lo contrario, te estarás pateando a ti mismo cuando te falte un punto clave de registro que definitivamente te diga cuál es el problema en la máquina del usuario.

(Nota: aquí me refiero al registro que ocurre cuando el modo de seguimiento está habilitado para registros orientados al desarrollador, no registros de funcionamiento normal orientados al usuario.)


Dado que log4net hace un gran trabajo para no obstruir los recursos, tiendo a ser un poco detallado al iniciar sesión porque cuando tienes que cambiar al modo de depuración, cuanta más información tienes, mejor. Esto es lo que normalmente registro:

Nivel de depuración

  • Cualquier parámetro pasado al método
  • Cualquier recuento de filas de conjuntos de resultados que recupero
  • Cualquier datarow que pueda contener datos sospechosos cuando se transmite al método
  • Cualquier ruta de archivo "generada", cadenas de conexión u otros valores que puedan confundirse al ser "ensamblados" por el entorno.

Nivel INFO

  • El inicio y el final del método
  • El inicio y el final de cualquier bucle importante
  • El comienzo de cualquier declaración importante de caso / cambio

Nivel de ERROR

  • Excepciones manejadas
  • Intentos de inicio de sesión inválidos (si la seguridad es un problema)
  • Malos datos que he interceptado para informar

Nivel FATAL

  • Excepciones no manejadas

Además, tener muchos datos de registro me impide preguntarle al usuario qué estaban haciendo cuando recibieron el mensaje de error. Puedo unirlo fácilmente.


Debo confesar que cuando comencé a programar, registré más o menos todos los detalles como lo describe "Dillie-O".

Créame ... Ayudó mucho durante los días iniciales de la implementación de la producción, donde confiamos mucho en los archivos de registro para resolver cientos de problemas.

Una vez que el sistema se estabiliza, lentamente comencé a eliminar las entradas de registro a medida que su valor agregado comenzaba a disminuir. (No Log4j en esos momentos).

Creo que la proporción de entradas de código a registro depende del proyecto y el entorno, y no tiene que ser una relación constante.

Hoy en día tenemos mucha flexibilidad para iniciar sesión con paquetes como Log4j, habilitación dinámica de nivel de registro, etc.

Pero si los programadores no lo usan apropiadamente, como cuándo usar, cuándo NO usar INFO, DEBUG, ERROR, etc., así como detalles en los mensajes de registro (He visto un mensaje de registro como, "Hola X, Hola XX, Hola XXX, etc. "que solo el programador puede entender), la relación seguirá siendo alta con menos ROI .


En mi línea de trabajo, escribo muchos servicios de Windows. Para mí, la tala no es un lujo; en realidad es mi única interfaz de usuario. Cuando implementamos en producción, perdemos acceso a la depuración e incluso las bases de datos a las que nuestros servicios escriben y sin iniciar sesión, no tendremos forma de conocer los detalles que surjan.

Habiendo dicho eso, creo que un estilo de registro conciso es el mejor enfoque. Los mensajes de registro tienden a limitarse a la lógica comercial de la aplicación, como "mensaje recibido de la cuenta xxx" que "función ingresada aaaa". Registramos excepciones, inicios de hilos, repetición de ajustes y tiempos del entorno. Más allá de eso, buscamos en el depurador identificar los errores lógicos en las fases de desarrollo y QA.


En realidad, hay una buena biblioteca para agregar el registro después del hecho como dices, PostSharp . Te permite hacerlo a través de programación basada en atributos, entre muchas otras cosas muy útiles más allá del simple registro.

Estoy de acuerdo con que lo que dices es un poco excesivo para iniciar sesión.

Algunos otros presentan algunos puntos buenos, especialmente el escenario bancario y otras aplicaciones de misión crítica. Puede ser necesario para el registro extremo, o al menos ser capaz de encenderlo y apagarlo si es necesario, o tener varios niveles establecidos.


Encuentro que el registro es mucho menos necesario desde que comencé a usar TDD. Hace que sea mucho más fácil determinar dónde se encuentran los errores. Sin embargo, encuentro que las declaraciones de registro pueden ayudar a entender qué está pasando en el código. Claro, los depuradores te ayudan a darte una idea de bajo nivel de lo que está sucediendo. Pero me resulta más fácil cuando puedo asociar una línea de salida a una línea de código si quiero obtener una vista de alto nivel de lo que está sucediendo.

Sin embargo, una cosa que debería agregar es esto: ¡asegúrese de que sus instrucciones de registro incluyan el módulo en el que se encuentra la sentencia de registro! No puedo contar la cantidad de veces que tuve que volver atrás y encontrar dónde se encuentra realmente una declaración de registro.


Esa cantidad de registro no es necesaria. No hay ninguna razón (en producción) para saber cuándo comienza y dónde termina cada método. Tal vez lo necesite en ciertos métodos, pero tener tanto ruido en los archivos de registro los hace casi imposibles de analizar de manera efectiva.

Debe iniciar sesión cuando suceden cosas importantes, como errores, inicios de sesión de usuarios (registro de auditoría), transacciones iniciadas, datos importantes actualizados ... etcétera. Si tiene un problema que no puede descifrar de los registros, puede agregar más si es necesario ... pero solo si es necesario.

Además, solo para su información, agregar el inicio de sesión en tiempo de compilación sería un ejemplo de lo que se denomina Programación Orientada a Aspectos . La tala sería la "preocupación transversal".


Los archivos de registro completos son increíblemente útiles. Considere una situación donde su aplicación se implementa en algún lugar como un banco. No puede entrar allí y depurarlo a mano y seguro que no le enviarán sus datos. Lo que puede obtener es un registro completo que puede indicar dónde ocurrió el problema. Tener varios niveles de registro es muy útil. Normalmente, la aplicación se ejecutará en un modo tal que solo informe sobre errores fatales o errores graves. Cuando necesite depurarlo, un usuario puede activar la salida de depuración o rastreo y obtener mucha más información.

El tipo de registro que está viendo parece excesivo, pero realmente no puedo decir que es cierto sin saber más sobre la aplicación y dónde podría implementarse.


Personalmente creo que antes que nada no hay una regla dura y rápida. Tengo algunas aplicaciones que registran mucho, dentro y fuera de métodos y actualizaciones de estado a través del medio. Sin embargo, estas aplicaciones son procesos programados, se ejecutan sin intervención, y los registros son analizados por otra aplicación que almacena éxito / falla.

He descubierto que, en realidad, muchas aplicaciones de usuario no necesitan grandes cantidades de registro, ya que en realidad si surgen problemas, se estará depurando para rastrear los valores allí. Además, normalmente no necesita el gasto de registro.

Sin embargo, realmente depende del proyecto.