paint-brush
Surveillance de Monolith avec Datadog : comment éviter l'effet spectateurpar@feddena
Nouvelle histoire

Surveillance de Monolith avec Datadog : comment éviter l'effet spectateur

par Fedor Denisov7m2024/07/08
Read on Terminal Reader

Trop long; Pour lire

Dans les grandes applications monolithiques, le suivi et la surveillance des erreurs deviennent souvent inefficaces en raison d’un manque de propriété claire. Ce guide aborde le problème en proposant une approche structurée pour attribuer des responsabilités via des annotations de domaine introduites dans la bibliothèque monolith-domain-splitter.
featured image - Surveillance de Monolith avec Datadog : comment éviter l'effet spectateur
Fedor Denisov HackerNoon profile picture
0-item

Dans les grandes applications monolithiques, le suivi et la surveillance des erreurs deviennent souvent inefficaces en raison d’un manque de propriété claire. Ce guide aborde le problème en proposant une approche structurée pour attribuer des responsabilités via des annotations de domaine.


Mettre en place une surveillance efficace pour un grand monolithique avec plusieurs équipes peut s'avérer difficile. Sans une appropriation claire, le suivi des erreurs devient générique et souvent ignoré. Une solution consiste à demander aux ingénieurs de garde d'identifier quelle équipe doit répondre aux alarmes de surveillance. Cependant, une approche plus efficace consiste à inclure les informations sur le domaine et l’équipe dans chaque journal et étendue Datadog.


Comprendre les annotations de domaine

Pour savoir quelle équipe est responsable des différentes parties de notre application, nous utilisons un système appelé Domain Annotations. Les annotations de domaine étiquettent chaque partie du code de votre application, indiquant clairement qui est responsable de quoi. Cela fournit une organisation et une responsabilité claires dans la gestion des responsabilités.

Les avantages de l'utilisation des annotations de domaine

Les annotations de domaine fournissent une méthode claire et organisée pour suivre les responsabilités de l'équipe au sein d'une application monolithique. En balisant des parties de votre code avec des annotations de domaine, vous pouvez :

  • Simplifiez la gestion des journaux et des traces : filtrez les journaux et les traces en fonction de critères spécifiques, tels que la responsabilité de l'équipe, permettant une identification et une résolution rapides des problèmes.
  • Maintenez un suivi précis : adaptez-vous de manière transparente aux changements dans les responsabilités de l'équipe, car les annotations sont liées au domaine plutôt qu'aux noms d'équipe.
  • Améliorer la responsabilité : définissez clairement quelle équipe est responsable de chaque domaine, améliorant ainsi l'organisation et le suivi ciblé.
  • Améliorer l'efficacité du suivi : Facilitez de meilleures pratiques de suivi en fournissant une responsabilité précise et en améliorant l'efficacité globale.

Traitement des annotations de domaine

Pour garantir une surveillance et une traçabilité efficaces, chaque requête Web est étiquetée avec les informations de domaine appropriées. Ceci est réalisé grâce à la collaboration de plusieurs composants : DomainProvider , DomainSpanService , DomainMdcProvider et DomainHandlerInterceptor .

Voici un aperçu général du processus décrit dans le diagramme suivant :

Schéma du traitement des annotations de domaine

Explication des composants clés

  • DomainProvider : identifie le domaine associé à des méthodes de gestion ou des beans spécifiques. Il aide à trouver des annotations de domaine dans les appels AOP (Aspect-Oriented Programming) et MVC (Model-View-Controller).
  • DomainSpanService : ajoute des balises de domaine aux étendues, qui sont des unités de travail dans les systèmes de traçage. Ce service garantit que chaque étendue est étiquetée avec les informations de domaine appropriées.
  • DomainMdcProvider : gère les balises de domaine au sein du MDC (Mapped Diagnostic Context), une fonctionnalité des frameworks de journalisation qui permet de baliser les entrées de journal avec des informations contextuelles.
  • DomainHandlerInterceptor : intercepte les requêtes Web, garantissant que chaque requête est étiquetée avec les informations de domaine appropriées pour une meilleure surveillance et traçabilité.

La mise en œuvre détaillée de ces composants sera encapsulée dans une bibliothèque partagée, fournissant une solution réutilisable pour le marquage et la surveillance des requêtes Web dans de grandes applications monolithiques.

Trier à qui appartient quel code

Définir la propriété au niveau de la classe est simple avec les annotations de domaine. En appliquant des annotations de niveau supérieur aux classes principales, la propriété se propage à toutes les ressources détaillées de ces classes. Chaque équipe peut étiqueter les classes qu'elle possède avec les annotations de domaine appropriées, garantissant ainsi clarté et responsabilité sans avoir besoin de marquer chaque méthode.


Dans les cas où plusieurs équipes possèdent du code dans une classe et qu'une refactorisation immédiate n'est pas appropriée, vous pouvez marquer des méthodes individuelles avec différentes annotations de domaine, qui ont la priorité sur les annotations au niveau de la classe. Cela permet d'attribuer des méthodes spécifiques à différentes équipes, offrant ainsi de la flexibilité sans compliquer la structure globale.

Surmonter les cas non pris en charge par les annotations

Bien que les annotations de domaine soient incroyablement utiles, il existe de rares cas où elles ne peuvent pas être utilisées. Par exemple, nous avons rencontré des problèmes avec la création de tâches Quartz, qui ne fonctionnaient pas de manière transparente avec les annotations de domaine en raison d'un conflit entre la logique AOP de Quartz et la logique AOP utilisée pour les annotations de domaine.

Pour les tâches et les processus qui ne peuvent pas être annotés directement, nous avons utilisé le DomainTagsService directement dans les implémentations des tâches. Cette approche nous a permis d'ajouter manuellement des balises de domaine dans la logique d'exécution du travail.

Voici un exemple de la façon dont nous avons intégré DomainTagsService dans une tâche Quartz :

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

Améliorez la surveillance et la visibilité avec les services artificiels

Bien que le fait de disposer de services séparés pour chaque équipe offre des avantages significatifs en matière de surveillance et de propriété, cela entraîne des coûts et des efforts élevés pour diviser le monolithe, ainsi que d'éventuelles dépenses de développement supplémentaires. Compte tenu de la possibilité d'améliorer les temps de construction avec Gradle lorsque le monolithe est divisé en modules, le maintien d'un monorepo pourrait être la solution la plus efficace dans de nombreux cas.

Introduction de services artificiels

Pour simplifier la surveillance des activités de chaque équipe dans Datadog, vous pouvez attribuer des noms de service artificiels aux différentes équipes. Cette approche garantit que chaque équipe dispose de sa propre section dédiée dans les outils de surveillance de Datadog. Bien que l’utilisation de noms de services artificiels puisse prêter à confusion si vous avez de nombreux services à gérer, cela devient gérable avec un nombre limité de services backend. L'ajout de préfixes à ces noms de services artificiels permet de maintenir l'organisation et la clarté de votre configuration Datadog, facilitant ainsi la distinction entre les différentes équipes et leurs responsabilités.


utiliser un diagramme au lieu de la capture d'écran ?? avoir un travailleur/une application Web n'a aucun sens ici

Services artificiels dans Datadog APM qui sont en fait une seule application

Pourquoi ne pas utiliser des services artificiels pour les journaux ?

L'utilisation de noms de service artificiels pour les journaux peut créer de la confusion, car la même entrée de journal peut apparaître sous différents services.


Par exemple, considérons deux points de terminaison utilisant le même service d'authentification. Si ces points de terminaison sont annotés avec des domaines différents, la logique d'authentification produira des journaux sous différents services artificiels. Cela pourrait prêter à confusion lors de l'exploration des journaux, car ils apparaissent sous plusieurs noms de services. Pour éviter ce problème, il est préférable d'appliquer des noms de service artificiels uniquement aux étendues regroupées dans des traces afin d'éviter toute confusion.


Celà a-t-il un sens? je ne pense pas que ce soit le cas


Voici une représentation visuelle de ce problème :

Raison pour ne pas utiliser de services artificiels pour les journaux

Utilisation de services artificiels dans la surveillance et les tableaux de bord

L'utilisation de services artificiels vous permet non seulement de travailler avec des traces APM, mais également de filtrer par service dans Datadog Metrics, qui sont stockées pendant une période prolongée, permettant ainsi de suivre les modifications sur une période prolongée.

Exemple de moniteur

Vous trouverez ci-dessous une capture d'écran d'un moniteur dans Datadog qui utilise le nom de service artificiel konsus-assets dans la requête :

Moniteur qui utilise le service artificiel « konsus-assets » dans la requête

Exemple de tableau de bord

Vous trouverez ci-dessous une capture d'écran d'un tableau de bord dans Datadog qui utilise le nom de service artificiel konsus-assets dans le filtre :

Tableau de bord qui utilise de faux services « konsus-assets » dans le filtre

En utilisant de faux services dans votre stratégie de surveillance, vous pouvez améliorer la visibilité et la responsabilité des activités de chaque équipe au sein d'une application monolithique. Cette approche simplifie le processus de création et de maintenance de moniteurs et de tableaux de bord spécifiques à une équipe, conduisant à une surveillance plus efficace et organisée dans Datadog.


Emballer

Les annotations de domaine offrent une approche simple pour simplifier la surveillance des applications monolithiques dans Datadog. En mettant en œuvre cette stratégie, vous pouvez améliorer la gérabilité des journaux, des étendues et des métriques, transformant ainsi votre configuration de surveillance en un outil adapté à des équipes spécifiques. Cela améliore la responsabilité et l'organisation et facilite un dépannage et une analyse des performances plus efficaces et efficients dans l'ensemble de votre application.

Points clés à retenir

  1. Propriété et responsabilité améliorées : en annotant des parties de votre code avec des annotations de domaine, vous pouvez définir clairement quelle équipe est responsable de chaque domaine. Cela facilite une meilleure organisation et un suivi ciblé.
  2. Gestion améliorée des journaux et des traces : les annotations de domaine vous permettent de filtrer à la fois les journaux et les traces en fonction de critères spécifiques, tels que la responsabilité de l'équipe, permettant une identification et une résolution rapides des problèmes.
  3. Flexibilité avec les services artificiels : l'utilisation de noms de services artificiels pour les étendues (et non pour les journaux) garantit que les journaux restent clairs et traçables jusqu'à leurs véritables origines, évitant ainsi toute confusion.
  4. Surmonter les défis d'intégration : dans les cas où les annotations ne peuvent pas être appliquées directement, comme avec certains frameworks d'exécution de tâches comme Quartz, l'utilisation de services comme DomainTagsService directement dans les implémentations de tâches garantit que la surveillance spécifique au domaine peut toujours être maintenue.

Approche étape par étape de l'utilisation des annotations de domaine :

  1. Définir des domaines et des équipes

    Cela va changer avec la lib !!!

    Créez des énumérations représentant différents domaines et équipes dans votre application :

    • @Domain est une annotation qui peut être appliquée à des classes ou des fonctions, en les marquant avec une valeur de domaine spécifique.
    • DomainValue est une énumération représentant différents domaines, chacun associé à une équipe.
    • Team est une énumération représentant les différentes équipes travaillant sur l'application.
     @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. Annoter les classes (et les méthodes si nécessaire)

     @Domain(DomainValue.USER_MANAGEMENT) class UserService { @Domain(DomainValue.PAYMENT_PROCESSING) fun processPayment() { ... } }
  3. Gérer les cas non pris en charge

    Pour les cas qui ne peuvent pas être annotés directement, utilisez directement DomainTagsService pour envelopper la logique

     fun executeNotSupportedByAnnotationsLogic() { domainTagsService.invoke(domain) { executeLogic() } }
  4. Surveiller avec Datadog

    Utilisez des filtres de service artificiels pour les moniteurs, les tableaux de bord et le filtrage des traces APM


En suivant ces étapes, vous pouvez implémenter efficacement les annotations de domaine dans votre application monolithique, garantissant ainsi une surveillance, une responsabilité et une efficacité globale améliorées.


Merci d'avoir lu le message!