Esta guía tiene como objetivo brindarle conocimientos y prácticas fundamentales para garantizar que pueda monitorear y solucionar problemas de sus servicios de manera más efectiva.
En el desarrollo de aplicaciones, el registro a menudo se pasa por alto, pero es un componente crucial para construir un sistema robusto y observable. Las prácticas de registro adecuadas pueden mejorar la visibilidad de su aplicación, profundizar su comprensión de su funcionamiento interno y mejorar el estado general de la aplicación.
Registro predeterminado
Incorporar mecanismos de registro predeterminados en los puntos de entrada de su aplicación es muy beneficioso. Este registro automático puede capturar interacciones esenciales y potencialmente incluir los argumentos del punto de entrada. Sin embargo, es fundamental tener cuidado, ya que registrar información confidencial, como contraseñas, podría representar riesgos para la privacidad y la seguridad.
Puntos de entrada comunes
- Puntos finales de API : registre detalles sobre solicitudes y respuestas entrantes
- Trabajos en segundo plano : registra los puntos de inicio del trabajo, los detalles de ejecución y los resultados.
- Eventos asincrónicos : registre el manejo de eventos asincrónicos e interacciones relacionadas
Registro completo
Cada acción importante que realice su aplicación debe generar una entrada de registro, particularmente aquellas acciones que alteran su estado. Este enfoque de registro exhaustivo es clave para identificar y abordar rápidamente los problemas cuando surgen, ofreciendo una visión transparente del estado y la funcionalidad de su aplicación. Esta diligencia en el registro garantiza un diagnóstico y mantenimiento más sencillos.
Elegir el nivel de registro apropiado
Adoptar niveles de registro adecuados es crucial para gestionar e interpretar la gran cantidad de datos generados por su aplicación. Al categorizar los registros según su gravedad y relevancia, garantiza que los problemas críticos se identifiquen y aborden rápidamente, mientras que la información menos urgente permanece accesible sin sobrecargar sus esfuerzos de monitoreo.
A continuación se muestra una guía para utilizar los niveles de registro de manera efectiva:
Nivel | Descripción y ejemplos | Uso aceptado | No aceptada |
---|---|---|---|
| Eventos fatales que detienen las operaciones del sistema. por ejemplo, conexión perdida a la base de datos | Errores críticos del sistema | Errores no críticos, como intentos fallidos de inicio de sesión del usuario. |
| Hay un problema pero el sistema puede continuar la ejecución y completar la operación solicitada. | Problemas potenciales que conducen a problemas | Cambios de estado de rutina |
| Información sobre las funciones normales de la aplicación, como la creación de cuentas de usuario o la escritura de datos. | cambios de estado | Operaciones de solo lectura sin cambios |
| Información de diagnóstico detallada, como el inicio/final del proceso. | Los pasos del proceso de registro no alteran el estado del sistema | Cambios de estado de rutina u operaciones de alta frecuencia. |
| El nivel más detallado, incluidas las entradas/salidas de métodos. | Comprender el flujo y los detalles de un proceso. | Registro de información confidencial |
Qué ID registrar: enfoque jerárquico
Al registrar acciones en su aplicación, incluir los ID de las entidades directamente involucradas es crucial para vincular la información del registro con los datos de la base de datos. Un enfoque jerárquico le ayuda a encontrar rápidamente todos los registros conectados a una parte específica de su aplicación vinculando elementos a sus grupos o categorías principales.
Por ejemplo, en lugar de registrar solo el ID de un chat cuando no se puede enviar un mensaje, también debes registrar los ID de la sala de chat y la empresa a la que pertenece. De esta manera, obtendrá más contexto y podrá ver el impacto más amplio del problema.
Ejemplo de entrada de registro:
Failed to send the message - chat=$roomId, chatRoomId=chatRoomId, company=$companyId
Ejemplo de registros de producción
A continuación se muestra un ejemplo de cómo podrían verse los registros de producción cuando se utiliza el enfoque jerárquico:
Consistencia y estandarización
Prefijos estándar
Estandarizar los formatos de registro en todos los equipos puede hacer que sus registros sean mucho más fáciles de leer y comprender. Aquí hay algunos prefijos estandarizados a considerar:
- empezando a hacer algo
- No se pudo hacer algo
- Terminé de hacer algo
- Se saltó hacer algo
- Reintentar hacer algo
Registrar valores de variables por separado
Separar los nombres y valores de las variables del cuerpo de los mensajes de registro ofrece varias ventajas:
- Simplifica la búsqueda y el análisis de registros: facilita el filtrado y la búsqueda de información específica
- Agiliza la creación de mensajes de registro: mantiene sencillo el proceso de escritura de mensajes de registro
- Evita el desorden de mensajes: los valores grandes no alterarán la legibilidad del mensaje de registro
Formato de registro de ejemplo:
Log message - valueName=value
Ejemplos de registros que utilizan prácticas propuestas
Ejemplo teórico
A continuación se muestran ejemplos de entradas de registro bien estructuradas que siguen las mejores prácticas analizadas:
2023-10-05 14:32:01 [INFO] Successful login attempt - userId=24543, teamId=1321312 2023-10-05 14:33:17 [WARN] Failed login attempt - userId=536435, teamId=1321312
Estos ejemplos demuestran:
- Prefijos de registro estandarizados : prefijos claros y consistentes como "Intento de inicio de sesión exitoso" e "Intento de inicio de sesión fallido" hacen que los registros sean fáciles de entender.
- Valores de variables separados : los nombres y valores de las variables están separados del mensaje de registro, lo que mantiene la claridad y simplifica las búsquedas.
- Legibilidad y coherencia : el formato estructurado garantiza que los registros sean fáciles de leer y analizar, lo que ayuda a solucionar problemas y monitorear de manera eficiente.
Ejemplo de registros de producción
A continuación se muestra un ejemplo de cómo podrían verse los registros de producción al utilizar las prácticas propuestas:
ID de seguimiento
Para asociar registros de manera efectiva con una acción de usuario específica, es crucial incluir un traceId
o, como también se le llama, correlationId
en sus registros. La identificación debe permanecer coherente en todos los registros generados por la lógica activada por ese punto de entrada, ofreciendo una vista clara de la secuencia de eventos.
Ejemplo de implementación
Si bien algunos servicios de monitoreo como Datadog brindan agrupación de registros de manera inmediata, esto también se puede implementar manualmente. En una aplicación Kotlin que usa Spring, puede implementar un ID de seguimiento para solicitudes REST usando un HandlerInterceptor.
@Component class TraceIdInterceptor : HandlerInterceptor { companion object { private const val TRACE_ID = "traceId" } override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean { val traceId = UUID.randomUUID().toString() MDC.put(TRACE_ID, traceId) return true } override fun afterCompletion(request: HttpServletRequest, response: HttpServletResponse, handler: Any, ex: Exception?) { MDC.remove(TRACE_ID) } }
Este interceptor genera un traceId
único para cada solicitud, lo agrega al MDC al comienzo de la solicitud y lo elimina una vez completada la solicitud.
Registros de ejemplo con traceId
La implementación de dicha agregación de registros le permitirá filtrar registros similares al ejemplo siguiente
Uso de UUID frente a ID largos en registros
En muchos sistemas, las entidades pueden usar UUID
o ID Long
como identificadores principales, mientras que algunos sistemas pueden usar ambos tipos de ID para diferentes propósitos. Comprender las implicaciones de cada tipo para fines de explotación forestal es fundamental para tomar una decisión informada.
Aquí hay un desglose de las cosas a considerar:
Legibilidad: las identificaciones Long
son más fáciles de leer y considerablemente más cortas, especialmente si no se encuentran en el extremo superior del rango Long
.
Valor único: los ID UUID
brindan singularidad en todo el sistema, lo que le permite buscar registros usando un ID sin enfrentar problemas de colisiones de ID. Las colisiones aquí significan que existe la posibilidad de que 2 entidades de tablas de base de datos no relacionadas tengan el mismo ID Long
.
Limitaciones del sistema : en sistemas que utilizan claves primarias largas como ID de entidad, agregar un ID UUID
aleatorio suele ser sencillo; en un sistema distribuido con ID de entidad UUID
podría resultar desafiante o costoso tener ID Long
específicamente para el registro.
Registros existentes: la coherencia en el tipo de ID utilizados en los registros es fundamental, al menos por entidad. Si el sistema ya produce registros para algunas entidades y no está considerando cambiarlos todos, es mejor seguir con el tipo que ya se utiliza para identificar la entidad. Se puede considerar el registro de ambas ID durante un período de transición, pero tener varias ID de forma permanente saturará los registros innecesariamente.
Conclusión
Las prácticas de registro adecuadas son esenciales para una observabilidad eficaz del servicio. Al incorporar registros completos, niveles de registro adecuados, ID de seguimiento y formatos de registro estandarizados, puede mejorar significativamente su capacidad para monitorear y solucionar problemas de sus aplicaciones. Estas prácticas mejoran la claridad y coherencia de sus registros, lo que facilita el diagnóstico y la resolución de problemas rápidamente.
¡Gracias por tomarse el tiempo de leer esta publicación!