Recientemente tuve que investigar un problema de campo para nuestra aplicación de gran empresa. Me horrorizaron los registros que tuve que revisar en un intento de encontrar el problema y al final del día los registros no ayudaron en nada a identificar / aislar el error.
Nota: Entiendo que no todos los errores se pueden descubrir a través de los registros. Esto no cambia el hecho de que los registros son horribles.
Hay algunos problemas obvios con nuestro registro que ya podemos intentar solucionar. No quiero enumerarlos aquí y no puedo simplemente mostrarle nuestros archivos de registro para que pueda dar consejos sobre qué hacer.
En cambio, para evaluar qué tan mal estamos haciendo en el frente de la tala, me gustaría saber:
- ¿Cuáles son algunas pautas , si las hay, cuando se trata de iniciar sesión para una aplicación, especialmente para aplicaciones grandes?
- ¿Hay algún patrón que deberíamos seguir o antipatrones que deberíamos tener en cuenta?
- ¿Es esto algo importante de arreglar o incluso puede arreglarse o todos los archivos de registro son simplemente enormes y necesita scripts adicionales para analizarlos?
Nota al margen: utilizamos log4j.
Trabajo con sistemas críticos de seguridad en tiempo real y el registro es a menudo la única forma de atrapar errores raros que aparecen una vez que hay luna azul cada martes 53 cuando hay luna llena, si me entiendes. Esto te hace obsesivo con el tema, así que me disculparé ahora si empiezo a hacer espuma en la boca. Lo siguiente se escribió para los registros de depuración de código nativo, pero la mayor parte también es aplicable al mundo administrado ...
Use archivos de registro de texto. Parece obvio, pero algunas personas intentan generar archivos de registro binarios: eso es tonto porque no necesito buscar una herramienta de lectura cuando estoy en el campo. Además, si se trata de texto y la depuración es detallada, existe una buena posibilidad de que el ingeniero de campo pueda leer el archivo y diagnosticar el problema sin tener que volver a consultarme. Todos ganan.
Diseño sistemas que son capaces de registrar casi todo, pero no enciendo todo por defecto. La información de depuración se envía a un cuadro de diálogo de depuración oculto que la marca de tiempo y la envía a un cuadro de lista (limitado a alrededor de 500 líneas antes de la eliminación), y el cuadro de diálogo me permite detenerlo, guardarlo en un archivo de registro automáticamente o desviarlo a un depurador adjunto. Ese desvío me permite ver la salida de depuración de múltiples aplicaciones, todas bien serializadas, lo que a veces puede ser un salvavidas. Yo solía utilizar niveles de registro numéricos (el más alto sea el nivel, más se captura):
pero esto es demasiado inflexible: a medida que avanza hacia un error, es mucho más eficiente poder concentrarse en iniciar sesión exactamente en lo que necesita sin tener que atravesar toneladas de detritos, y puede ser un tipo particular de transacción u operación eso causa el error. Si eso requiere que encienda todo, solo está haciendo su propio trabajo más difícil. Necesitas algo más fino.
Así que ahora estoy en el proceso de cambiar al registro basado en un sistema de bandera. 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 qué se registra. Por lo general, esa lista se ve así:
Este sistema de registro se envía con la versión de lanzamiento , activada y guardada en el archivo de forma predeterminada. Es demasiado tarde para descubrir que debería haber estado iniciando sesión DESPUÉS de que ocurrió el error, si ese error solo ocurre una vez cada seis meses en promedio y no tiene forma de reproducirlo. El registro que solo funciona con compilaciones de depuración es justo. llanura. tonto.
El software generalmente se entrega 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 estas cosas).
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 comience cada archivo con la fecha, la versión del código que está ejecutando y, si es posible, algún marcador para la identificación del cliente, la ubicación del sistema o lo que sea. Puede obtener una mezcla de archivos de registro desde el campo, y necesita un registro de lo que vino de dónde y qué versión del sistema estaban ejecutando que está realmente en los datos, y no puede confiar en el cliente / ingeniero de campo para decirte qué versión tienen, pueden simplemente decirte qué versión piensan que tienen. Peor aún, pueden informar la versión exe que está en el disco, pero la versión anterior todavía se está ejecutando porque olvidaron reiniciar después de reemplazarla. Haz que tu código te lo diga a ti mismo.
Por último, no desea que su código genere sus propios problemas, por lo tanto, coloque una función de temporizador para purgar los archivos de registro después de tantos días o semanas (solo verifique la diferencia entre la hora actual y la hora de creación del archivo). Esto está bien para una aplicación de servidor que se ejecuta todo el tiempo, en una aplicación del lado del cliente que puede solucionar purgando los datos antiguos cuando se inicia. Por lo general, purgamos después de aproximadamente 30 días, en un sistema sin visitas frecuentes de ingenieros, es posible que desee dejarlo más tiempo. Obviamente, esto también depende del tamaño de sus archivos de registro.
fuente
Mi recurso público favorito para las pautas de registro son las mejores prácticas de Apache JCL .
A pesar de apuntar a JCL, estos parecen ser lo suficientemente genéricos como para ser adoptados para el registro en general.
El anti-patrón más famoso es probablemente "tragar excepciones" - solo búscalo en la web.
En cuanto a los archivos de registro enormes, en mi práctica este fue principalmente el caso normal. Y sí, los scripts complementarios como los llama y / o herramientas como Chainsaw también me parecen normales.
PD. Con respecto a los antipatrones, otros que vienen a la mente son "inundaciones" y mensajes sin sentido.
Lo llamo inundación cuando veo múltiples mensajes similares provenientes de un bucle con muchas iteraciones. Para mí, las inundaciones son lo suficientemente molestas como para tratar de deshacerme de ellas cuando las detecto en el código fuente. Por lo general, mejorarlo requiere algo de arte, porque, bueno, las cosas que suceden dentro del ciclo pueden ser interesantes. Cuando no tengo tiempo para mejorarlo más, intento al menos cambiar el nivel de registro de dichos mensajes al más bajo para que sea más fácil filtrarlo.
Los mensajes sin sentido parecen ser basura bastante popular. Estos se ven inofensivos cuando se leen en el código fuente; supongo que uno tiene que pasar por el dolor de analizar la salida de depuración con el aspecto de ...
... para apreciar profundamente su fealdad inherente. Mi heurística favorita para detectar este tipo de problemas a nivel de código fuente (propuesta por un colega en uno de mis proyectos anteriores) es calcular la cantidad de ocurrencias de símbolos de espacio en literales de cadena utilizados en el registro. En mi experiencia, cero espacios básicamente garantiza que la declaración de registro no tenga sentido, un espacio también es un buen indicador del posible problema.
fuente
somethingSpecialHappenedCount
) y luego enviarse al registrador.¡Registre la excepción solo una vez!
Uno de los puntos de dolor comunes que he notado es iniciar sesión y volver a lanzar una excepción. Como resultado, los archivos de registro contienen las mismas excepciones varias veces en varios niveles de pila.
fuente
Aquí hay un antipatrón: hacer dos docenas de campos "genéricos variables" en una tabla de base de datos para rastrear cualquier cosa concebible y luego tener 88 (y contar) diferentes valores de enumeración para diferentes tipos de registros.
fuente
Mi experiencia con los registros es cuanto más grande mejor, pero ser lo suficientemente consistente como para que se pueda filtrar por máquina y poder configurar un nivel de gravedad para cada componente de su aplicación individualmente.
Además, es muy difícil predecir qué registro necesitará para encontrar un error futuro. La mayoría de los lugares obvios para registrar errores se solucionan antes de que el producto salga por la puerta. No es raro que el resultado de un informe de error sea que acaba de agregar el registro para ayudar a diagnosticarlo si vuelve a ocurrir.
fuente
Un par de notas del lado de operaciones de la casa aquí:
1) Asegúrese de que los registros sean configurables localmente, preferiblemente con una herramienta no más pesada que un editor de texto. La mayoría de las veces no queremos obtener el registro de nivel TRACE, pero nos encanta poder activarlo.
2) Si es posible, asegúrese de que los registros se puedan leer con una herramienta que no sea más pesada que un editor de texto. Nada es peor que tener que buscar herramientas a una hora extraña cuando el sistema de producción falla.
fuente
Desde mi propia experiencia trabajando con aplicaciones web:
(y considerando que el almacenamiento es muy barato hoy en día)
Sea coherente con sus cadenas de registro. Como siempre uso este tipo de patrón:
fuente
Además del stacktrace, registre el estado actual de la aplicación y la entrada.
El software es determinista, estos dos son generalmente lo único que necesita para reproducir el error. El almacenamiento del estado completo puede ser problemático en algunos casos, por lo que las formas de reproducir el estado actual, por ejemplo, mediante entradas anteriores, también son buenas.
Por supuesto, más datos siempre es mejor, pero como mínimo estos dos son un buen comienzo para los bloqueos más fáciles.
fuente