paint-brush
Monitoreo de monolito con Datadog: cómo evitar el efecto espectadorpor@feddena
Nueva Historia

Monitoreo de monolito con Datadog: cómo evitar el efecto espectador

por Fedor Denisov7m2024/07/08
Read on Terminal Reader

Demasiado Largo; Para Leer

En aplicaciones monolíticas de gran tamaño, el seguimiento y la supervisión de errores a menudo se vuelven ineficaces debido a la falta de una propiedad clara. Esta guía aborda el problema proponiendo un enfoque estructurado para asignar responsabilidades a través de anotaciones de dominio introducidas en la biblioteca monolith-domain-splitter.
featured image - Monitoreo de monolito con Datadog: cómo evitar el efecto espectador
Fedor Denisov HackerNoon profile picture
0-item

En aplicaciones monolíticas de gran tamaño, el seguimiento y la supervisión de errores a menudo se vuelven ineficaces debido a la falta de una propiedad clara. Esta guía aborda el problema proponiendo un enfoque estructurado para asignar responsabilidades a través de anotaciones de dominio.


Configurar un monitoreo efectivo para grandes monolíticos con múltiples equipos puede ser un desafío. Sin una propiedad clara, el seguimiento de errores se vuelve genérico y a menudo se ignora. Una solución es hacer que los ingenieros de guardia identifiquen qué equipo debe responder a las alarmas de monitoreo. Sin embargo, un enfoque más eficiente es incluir información del dominio y del equipo en cada registro y tramo de Datadog.


Comprender las anotaciones de dominio

Para realizar un seguimiento de qué equipo es responsable de las distintas partes de nuestra aplicación, utilizamos un sistema llamado Anotaciones de Dominio. Las anotaciones de dominio etiquetan cada parte del código de su aplicación, indicando claramente quién es responsable de qué. Esto proporciona una organización clara y responsabilidad en la gestión de responsabilidades.

Los beneficios de utilizar anotaciones de dominio

Las anotaciones de dominio proporcionan un método claro y organizado para realizar un seguimiento de las responsabilidades del equipo dentro de una aplicación monolítica. Al etiquetar partes de su código con anotaciones de dominio, puede:

  • Simplifique la gestión de registros y seguimientos : filtre registros y seguimientos según criterios específicos, como la responsabilidad del equipo, lo que permite una rápida identificación y resolución de problemas.
  • Mantenga un seguimiento preciso : adáptese sin problemas a los cambios en las responsabilidades del equipo, ya que las anotaciones están vinculadas al dominio en lugar de a los nombres de los equipos.
  • Mejore la responsabilidad : defina claramente qué equipo es responsable de cada dominio, mejorando la organización y el seguimiento específico.
  • Mejorar la eficiencia del monitoreo : facilitar mejores prácticas de monitoreo proporcionando una rendición de cuentas precisa y mejorando la eficiencia general.

Procesamiento de anotaciones de dominio

Para garantizar un seguimiento y una trazabilidad eficientes, cada solicitud web se etiqueta con la información de dominio adecuada. Esto se logra mediante la colaboración de varios componentes: DomainProvider , DomainSpanService , DomainMdcProvider y DomainHandlerInterceptor .

A continuación se ofrece una descripción general de alto nivel del proceso que se muestra en el siguiente diagrama:

Diagrama de procesamiento de anotaciones de dominio

Explicación de los componentes clave

  • DomainProvider : identifica el dominio asociado con beans o métodos de controlador específicos. Ayuda a encontrar anotaciones de dominio en llamadas AOP (Programación orientada a aspectos) y MVC (Modelo-Vista-Controlador).
  • DomainSpanService : agrega etiquetas de dominio a tramos, que son unidades de trabajo en los sistemas de seguimiento. Este servicio garantiza que cada tramo esté etiquetado con la información de dominio adecuada.
  • DomainMdcProvider : gestiona etiquetas de dominio dentro del MDC (contexto de diagnóstico asignado), una característica de los marcos de registro que permite etiquetar entradas de registro con información contextual.
  • DomainHandlerInterceptor : intercepta solicitudes web y garantiza que cada solicitud esté etiquetada con la información de dominio adecuada para un mejor seguimiento y trazabilidad.

La implementación detallada de estos componentes se encapsulará en una biblioteca compartida, proporcionando una solución reutilizable para etiquetar y monitorear solicitudes web en grandes aplicaciones monolíticas.

Determinar quién posee qué código

Definir la propiedad a nivel de clase es sencillo con las anotaciones de dominio. Al aplicar anotaciones de nivel superior a las clases principales, la propiedad se propaga a todos los recursos detallados dentro de esas clases. Cada equipo puede etiquetar las clases de su propiedad con las anotaciones de dominio adecuadas, lo que garantiza claridad y responsabilidad sin la necesidad de marcar cada método.


En los casos en que varios equipos poseen código en una clase y la refactorización inmediata no es apropiada, puede marcar métodos individuales con diferentes anotaciones de dominio, que tienen prioridad sobre las anotaciones a nivel de clase. Esto permite asignar métodos específicos a diferentes equipos, lo que proporciona flexibilidad sin complicar la estructura general.

Superación de casos no respaldados por anotaciones

Si bien las anotaciones de dominio son increíblemente útiles, hay casos raros en los que no se pueden utilizar. Por ejemplo, encontramos problemas con la creación de trabajos de Quartz, que no funcionaba perfectamente con las anotaciones de dominio debido a un choque entre la lógica AOP de Quartz y la lógica AOP utilizada para las anotaciones de dominio.

Para trabajos y procesos que no se pueden anotar directamente, utilizamos DomainTagsService directamente en las implementaciones de trabajos. Este enfoque nos permitió agregar manualmente etiquetas de dominio dentro de la lógica de ejecución del trabajo.

A continuación se muestra un ejemplo de cómo integramos DomainTagsService en un trabajo de Quartz:

 final override fun execute(context: JobExecutionContext) { domainTagsService.invoke(domain) { withLoggedExecutionDetails(context, ::doExecute) } }

Mejore el monitoreo y la visibilidad con servicios artificiales

Si bien tener servicios separados para cada equipo ofrece ventajas significativas en cuanto a monitoreo y propiedad, conlleva altos costos y esfuerzos para dividir el monolito, junto con posibles gastos de desarrollo adicionales. Teniendo en cuenta la posibilidad de mejorar los tiempos de compilación con Gradle cuando el monolito se divide en módulos, mantener un monorepo podría ser la solución más eficiente en muchos casos.

Introducción de servicios artificiales

Para simplificar el seguimiento de las actividades de cada equipo en Datadog, puede asignar nombres de servicios artificiales para grupos de diferentes equipos. Este enfoque garantiza que cada equipo tenga su propia sección dedicada en las herramientas de monitoreo de Datadog. Si bien el uso de nombres de servicios artificiales puede resultar confuso si tiene muchos servicios que administrar, resulta manejable con una cantidad limitada de servicios backend. Agregar prefijos a estos nombres de servicios artificiales ayuda a mantener la organización y la claridad en la configuración de Datadog, lo que facilita la distinción entre diferentes equipos y sus responsabilidades.


¿Usar diagrama en lugar de captura de pantalla? tener trabajador/aplicación web no tiene sentido aquí

Servicios artificiales en Datadog APM que en realidad son una sola aplicación

¿Por qué no utilizar servicios artificiales para los registros?

El uso de nombres de servicios artificiales para los registros puede crear confusión, ya que la misma entrada de registro puede aparecer en diferentes servicios.


Por ejemplo, considere dos puntos finales que utilizan el mismo servicio de autenticación. Si estos puntos finales están anotados con diferentes dominios, la lógica de autenticación producirá registros en diferentes servicios artificiales. Esto podría causar confusión cuando se exploran registros, ya que aparecen bajo varios nombres de servicios. Para evitar este problema, es mejor aplicar nombres de servicios artificiales solo a intervalos que se agregan en seguimientos para que haya menos confusión.


¿Tiene algún sentido? no creo que lo sea


Aquí hay una representación visual de este problema:

Razonamiento detrás de no utilizar servicios artificiales para registros

Uso de servicios artificiales en monitoreo y paneles

El uso de servicios artificiales le permite no solo trabajar con seguimientos de APM, sino también filtrar por servicio en Datadog Metrics, que se almacenan durante un período prolongado, lo que permite realizar un seguimiento de los cambios durante un período prolongado.

Ejemplo de monitor

A continuación se muestra una captura de pantalla de un monitor en Datadog que utiliza el nombre de servicio artificial konsus-assets en la consulta:

Monitor que utiliza el servicio artificial 'konsus-assets' en la consulta

Ejemplo de panel

A continuación se muestra una captura de pantalla de un panel en Datadog que utiliza el nombre de servicio artificial konsus-assets en el filtro:

Panel que utiliza el servicio falso 'konsus-assets' en el filtro

Al utilizar servicios falsos en su estrategia de monitoreo, puede mejorar la visibilidad y la responsabilidad de las actividades de cada equipo dentro de una aplicación monolítica. Este enfoque simplifica el proceso de creación y mantenimiento de monitores y paneles de control específicos del equipo, lo que lleva a un monitoreo más efectivo y organizado en Datadog.


Terminando

Las anotaciones de dominio proporcionan un enfoque sencillo para simplificar el monitoreo de aplicaciones monolíticas en Datadog. Al implementar esta estrategia, puede mejorar la capacidad de administración de registros, intervalos y métricas, transformando su configuración de monitoreo en una herramienta adaptada a equipos específicos. Esto mejora la responsabilidad y la organización y facilita una solución de problemas y un análisis de rendimiento más efectivos y eficientes en toda su aplicación.

Conclusiones clave

  1. Propiedad y responsabilidad mejoradas : al anotar partes de su código con anotaciones de dominio, puede definir claramente qué equipo es responsable de cada dominio. Esto facilita una mejor organización y un seguimiento específico.
  2. Gestión mejorada de registros y rastreos : las anotaciones de dominio le permiten filtrar registros y rastreos según criterios específicos, como la responsabilidad del equipo, lo que permite una rápida identificación y resolución de problemas.
  3. Flexibilidad con servicios artificiales : el uso de nombres de servicios artificiales para tramos (no registros) garantiza que los registros permanezcan claros y rastreables hasta sus verdaderos orígenes, evitando confusiones.
  4. Superar los desafíos de integración : en los casos en los que las anotaciones no se pueden aplicar directamente, como con ciertos marcos de ejecución de trabajos como Quartz, el uso de servicios como DomainTagsService directamente en las implementaciones de trabajos garantiza que aún se pueda mantener el monitoreo específico del dominio.

Enfoque paso a paso para utilizar anotaciones de dominio:

  1. Definir dominios y equipos

    ¡¡¡Eso cambiará con la lib !!!

    Cree enumeraciones que representen diferentes dominios y equipos en su aplicación:

    • @Domain es una anotación que se puede aplicar a clases o funciones, marcándolas con un valor de dominio específico.
    • DomainValue es una enumeración que representa diferentes dominios, cada uno asociado con un equipo.
    • Team es una enumeración que representa los distintos equipos que trabajan en la aplicación.
     @Retention(AnnotationRetention.RUNTIME) @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) annotation class Domain(val value: DomainValue) enum class DomainValue(val team: Team) { USER_MANAGEMENT(Team.TEAM_A), PAYMENT_PROCESSING(Team.TEAM_B), NOTIFICATIONS(Team.TEAM_C) } enum class Team { TEAM_A, TEAM_B, TEAM_C }
  2. Anotar clases (y métodos si es necesario)

     @Domain(DomainValue.USER_MANAGEMENT) class UserService { @Domain(DomainValue.PAYMENT_PROCESSING) fun processPayment() { ... } }
  3. Manejar casos no admitidos

    Para los casos que no se pueden anotar directamente, use DomainTagsService directamente para ajustar la lógica.

     fun executeNotSupportedByAnnotationsLogic() { domainTagsService.invoke(domain) { executeLogic() } }
  4. Monitorear con Datadog

    Utilice filtros de servicio artificiales para monitores, paneles y filtrado de seguimiento de APM


Si sigue estos pasos, podrá implementar de forma eficaz anotaciones de dominio en su aplicación monolítica, lo que garantizará una mejor supervisión, responsabilidad y eficiencia general.


¡Gracias por leer la publicación!