BE engineer, Kotlin/Java, computer vision
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.
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.
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.
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 |
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.
Failed to send the message - chat=$roomId, chatRoomId=chatRoomId, company=$companyId
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:
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:
Separar los nombres y valores de las variables del cuerpo de los mensajes de registro ofrece varias ventajas:
Log message - valueName=value
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:
A continuación se muestra un ejemplo de cómo podrían verse los registros de producción al utilizar las prácticas propuestas:
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.
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.
La implementación de dicha agregación de registros le permitirá filtrar registros similares al ejemplo siguiente
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.
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!
Lograr el registro correcto: Observability Foundation | HackerNoon