Ce tutoriel détaille les étapes permettant l’activation du tracing sur un exemple d’application Go installée dans un conteneur. Pour cet exemple, l’Agent Datadog est également installé dans le conteneur.
Pour les autres scénarios, y compris lʼapplication et lʼAgent sur un host, lʼapplication et lʼAgent sur une infrastructure dans le cloud, et sur les applications écrites dans dʼautres langages, consultez les autres tutoriels relatifs à lʼactivation du tracing.
Référez-vous à la section Tracer des applications Go pour consulter la documentation complète relative à la configuration du tracing pour Go.
Installer lʼexemple dʼapplication Go conteneurisée
L’exemple de code pour ce tutoriel se trouve sur GitHub, à l’adresse suivante : github.com/DataDog/apm-tutorial-golang.git. Pour commencer, dupliquez le référentiel git :
Ce référentiel contient une application Go dotée de plusieurs services, préconfigurée pour être exécutée au sein des conteneurs de Docker. Dans cet exemple, lʼapp est une app de note basique et une app de calendrier, chacune dotée dʼune API REST pour ajouter et modifier des données. Les fichiers YAML docker-compose sont situés dans le répertoire docker.
Ce tutoriel utilise le fichier all-docker-compose.yaml, qui crée des conteneurs pour les applications de notes et de calendrier, ainsi que pour lʼAgent Datadog.
Débuter et sʼentraîner avec lʼexemple dʼapplication
Créez les conteneurs de lʼapplication en exécutant :
docker-compose -f all-docker-compose.yaml build
Démarrez les conteneurs :
docker-compose -f all-docker-compose.yaml up -d
Vérifiez que les conteneurs s’exécutent correctement avec la commande docker ps. La sortie devrait ressembler à ceci :
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0a4704ebed09 docker-notes "./cmd/notes/notes" About a minute ago Up About a minute 0.0.0.0:8080->8080/tcp notes
9c428d7f7ad1 docker-calendar "./cmd/calendar/cale..." About a minute ago Up About a minute 0.0.0.0:9090->9090/tcp calendar
b2c2bafa6b36 gcr.io/datadoghq/agent:latest "/bin/entrypoint.sh" About a minute ago Up About a minute (unhealthy) 8125/udp, 8126/tcp datadog-ag
L’exemple d’application notes est une API REST standard qui stocke des données dans une base de données en mémoire. Utilisez curl pour envoyer quelques requêtes d’API :
curl localhost:8080/notes
Renvoie [] car il n’y a encore rien dans la base de données.
curl -X POST 'localhost:8080/notes?desc=hello'
Ajoute une note avec la description hello et une valeur dʼID de 1. Renvoie {"id":1,"description":"hello"}.
curl localhost:8080/notes/1
Renvoie la note dont la valeur id est 1 : {"id":1,"description":"hello"}
curl -X POST 'localhost:8080/notes?desc=otherNote'
Ajoute une note avec la description otherNote et une valeur dʼID de 2. Renvoie {"id":2,"description":"otherNote"}.
curl localhost:8080/notes
Renvoie le contenu de la base de données : [{"id":1,"description":"hello"},{"id";2,"description":"otherNote"}]
Exécutez d’autres appels API pour voir l’application en action. Lorsque vous avez terminé, arrêtez et retirez les conteneurs et assurez-vous qu’ils ont été retirés :
docker-compose -f all-docker-compose.yaml down
docker-compose -f all-docker-compose.yaml rm
Activer le tracing
Configurez ensuite l’application Go pour activer le traçage. Comme l’Agent s’exécute sur un conteneur, il n’est pas nécessaire d’installer quoi que ce soit.
Pour activer la prise en charge du traçage, supprimez la mise en commentaire l-des importations suivantes dans apm-tutorial-golang/cmd/notes/main.go :
Supprimez la mise en commentaire des champs depends_on pour datadog-agent dans le conteneur notes.
Vous noterez que dans la section du service notes, la variable dʼenvironnement DD_AGENT_HOST est définie sur le hostname du conteneur de lʼAgent. Votre section du conteneur notes devrait ressembler à ceci :
Vous configurerez les sections et les variables de calendar plus loin dans ce tutoriel.
Démarrer les conteneurs pour explorer lʼinstrumentation automatique
Maintenant que la bibliothèque de tracing est installée, lancez les conteneurs de votre application et commencez à recevoir des traces. Exécutez les commandes suivantes :
docker-compose -f all-docker-compose.yaml build
docker-compose -f all-docker-compose.yaml up -d
Pour commencer à générer et à collecter des traces, lancez à nouveau l’application avec make run.
Vous pouvez savoir si l’Agent fonctionne en observant les sorties en continu du terminal, ou en ouvrant l’explorateur d’événements dans Datadog et en affichant l’événement de départ de l’Agent :
Utilisez curl pour envoyer à nouveau des demandes à l’application :
curl localhost:8080/notes
[]
curl -X POST 'localhost:8080/notes?desc=hello'
{"id":1,"description":"hello"}
curl localhost:8080/notes/1
{"id":1,"description":"hello"}
curl localhost:8080/notes
[{"id":1,"description":"hello"}]
Attendez quelques instants et jetez un coup d’œil à votre IU Datadog. Accédez à APM > Traces. La liste des traces ressemble à ceci :
Il y a des entrées pour la base de données (db) et l’application notes. La liste des traces montre tous les spans, leur date de début, la ressource suivie avec le span et la durée.
Si aucune trace ne s’affiche, effacez les filtres actifs dans le champ Traces Search (il peut arriver qu’une variable d’environnement telle que ENV soit filtrée alors que vous ne l’utilisez pas).
Examiner une trace
Sur la page Traces, cliquez sur une trace POST /notes. Cela affiche un flamegraph décrivant la durée de chaque span ainsi que les autres spans présentes avant la finalisation d’une span. La barre située en haut du graphique représente la span que vous avez sélectionnée sur l’écran précédent (dans le cas présent, le point d’entrée initial dans l’application notes).
La largeur d’une barre indique la durée totale de la span. Une barre moins large représente une span finalisée pendant le cycle de vie d’une barre plus large.
Le flamegraph d’une trace POST ressemble à ceci :
Une trace GET /notes ressemble à ceci :
Configuration de tracing
Vous pouvez configurer la bibliothèque de traces de façon à ce quʼelle ajoute des tags à la télémétrie qu’elle envoie à Datadog. Les tags permettent de regrouper, filtrer et afficher les données de manière significative dans des dashboards et des graphiques. Pour ajouter des tags, spécifiez les variables dʼenvironnement lors de l’exécution de l’application. Le projet Makefile comprend les variables dʼenvironnement DD_ENV, DD_SERVICE et DD_VERSION, qui sont configurées de façon à activer le tagging de service unifié :
Pour en savoir plus sur les options de configuration disponibles, référez-vous à la section Configuring the Go Tracing Library (en anglais).
Utiliser les bibliothèques de tracing automatiques
Datadog propose plusieurs bibliothèques entièrement compatibles pour Go qui permettent un traçage automatique lorsqu’elles sont implémentées dans le code. Dans le fichier cmd/notes/main.go, vous pouvez voir les bibliothèques go-chi, sql, et http être aliasés vers les bibliothèques Datadog correspondantes : chitrace, sqltrace et httptrace respectivement :
Dans cmd/notes/main.go, les bibliothèques Datadog sont initialisées avec l’option WithServiceName. Par exemple, la bibliothèque chitrace est initialisée comme suit :
L’utilisation de chitrace.WithServiceName("notes") garantit que tous les éléments tracés par la bibliothèque relèvent du nom de service notes.
Le fichier main.go contient d’autres exemples d’implémentation pour chacune de ces bibliothèques. Pour obtenir la liste complète des bibliothèques, référez-vous à la section Exigences de compatibilité Go.
Utiliser le traçage personnalisé avec du contexte
Lorsque le code ne relève pas d’une bibliothèque prise en charge, vous pouvez créer des spans manuellement.
Supprimez les commentaires autour de la fonction makeSpanMiddleware dans notes/notesController.go. Il génère un intergiciel qui enveloppe une requête dans un span avec le nom fourni. Pour utiliser cette fonction, commentez les lignes suivantes :
notes/notesController.go
r.Get("/notes",nr.GetAllNotes)// GET /notes
r.Post("/notes",nr.CreateNote)// POST /notes
r.Get("/notes/{noteID}",nr.GetNoteByID)// GET /notes/123
r.Put("/notes/{noteID}",nr.UpdateNoteByID)// PUT /notes/123
r.Delete("/notes/{noteID}",nr.DeleteNoteByID)// DELETE /notes/123
Supprimez les commentaires autour des lignes suivantes :
notes/notesController.go
r.Get("/notes",makeSpanMiddleware("GetAllNotes",nr.GetAllNotes))// GET /notes
r.Post("/notes",makeSpanMiddleware("CreateNote",nr.CreateNote))// POST /notes
r.Get("/notes/{noteID}",makeSpanMiddleware("GetNote",nr.GetNoteByID))// GET /notes/123
r.Put("/notes/{noteID}",makeSpanMiddleware("UpdateNote",nr.UpdateNoteByID))// PUT /notes/123
r.Delete("/notes/{noteID}",makeSpanMiddleware("DeleteNote",nr.DeleteNoteByID))// DELETE /notes/123
Supprimez également le commentaire autour de l’importation suivante :
notes/notesController.go
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
L’exemple d’application contient plusieurs exemples de traçage personnalisé. En voici quelques autres. Supprimez les commentaires pour activer ces spans :
La fonction doLongRunningProcess crée des spans enfant à partir d’un contexte parent :
notes/notesHelper.go
funcdoLongRunningProcess(ctxcontext.Context){childSpan,ctx:=tracer.StartSpanFromContext(ctx,"traceMethod1")childSpan.SetTag(ext.ResourceName,"NotesHelper.doLongRunningProcess")deferchildSpan.Finish()time.Sleep(300*time.Millisecond)log.Println("Bonjour depuis le processus au long cours dans Notes")privateMethod1(ctx)}
La fonction privateMethod1 illustre la création d’un service totalement distinct d’un contexte :
notes/notesHelper.go
funcprivateMethod1(ctxcontext.Context){childSpan,_:=tracer.StartSpanFromContext(ctx,"manualSpan1",tracer.SpanType("web"),tracer.ServiceName("noteshelper"),)childSpan.SetTag(ext.ResourceName,"privateMethod1")deferchildSpan.Finish()time.Sleep(30*time.Millisecond)log.Println("Bonjour depuis la méthode personnalisée privateMethod1 dans Notes")}
Pour en savoir plus sur les traces personnalisées, consultez la section Go Custom Instrumentation (en anglais).
Ajouter une deuxième application pour voir ses traces distribuées
Le tracing d’une seule application est un excellent début. Toutefois, le tracing sert surtout à voir la façon dont les requêtes circulent dans vos services. On appelle ceci le tracing distribué.
L’exemple de projet comprend une deuxième application, appelée calendar, qui renvoie une date aléatoire lorsqu’elle est appelée. L’endpoint POST dans l’application Notes possède un deuxième paramètre de requête appelé add_date. Lorsque la valeur est y, lʼapplication de notes appelle l’application de calendrier pour obtenir une date à ajouter à la note.
Pour activer le tracing dans l’application de calendrier :
Supprimez la mise en commentaire des lignes suivantes dans cmd/calendar/main.go :
Ouvrez docker/all-docker-compose.yaml et supprimez la mise en commentaire du service calendar pour configurer le host de lʼAgent et les tags de service unifié pour l’application et pour Docker :
Dans la section du service notes, décommentez la variable dʼenvironnement CALENDAR_HOST et l’entrée calendar dans depends_on pour établir les connexions nécessaires entre les deux applications. Votre service de notes devrait ressembler à ceci :
Dans le Trace Explorer, cliquez sur la dernière trace notes pour afficher une trace distribuée entre les deux services :
Ce flamegraph combine les interactions de plusieurs applications :
La première span est une requête POST envoyée par l’utilisateur et traitée par le routeur chi par l’intermédiaire de la bibliothèque go-chi compatible.
Le deuxième span est une fonction createNote qui a été tracée manuellement par la fonction makeSpanMiddleware. La fonction a créé un span à partir du contexte de la requête HTTP.
Le span suivant est la requête envoyée par l’application de notes utilisant la bibliothèque http compatible et le client initialisé dans le fichier main.go. Cette requête GET est envoyée à l’application de calendrier. Les spans de l’application de calendrier apparaissent en bleu parce qu’il s’agit de deux services distincts.
Dans l’application de calendrier, un routeur go-chi traite la requête GET et la fonction GetDate est tracée manuellement avec son propre span sous la requête GET.
Enfin, l’appel db violet est un service à part entière à partir de la bibliothèque sql compatible. Il apparaît au même niveau que la requête GET /Calendar car ils sont tous deux appelés par le span parent CreateNote.
Dépannage
Si vous ne recevez pas les traces comme prévu, configurez le mode debugging pour le traceur Go. Consultez la rubrique Activer le mode debugging pour en savoir plus.
Pour aller plus loin
Documentation, liens et articles supplémentaires utiles: