Dev Life

Présentation d’un débogueur multiplateforme pour Go

Nous utilisons Go pour une grande partie de notre développement de serveurs ici chez Mailgun, et c'est génial. Cependant, venant de Python, il y a une chose qui m'a vraiment manqué :
Image pour Présentation d’un débogueur multiplateforme pour Go

Nous utilisons Go pour une grande partie de notre développement de serveurs ici chez Mailgun, et c’est génial. Cependant, venant de Python, il y a une chose qui m’a vraiment manqué :

Je pouvais insérer cette petite ligne chaque fois que je ne comprenais pas ce qui se passait dans le code pour voir exactement ce qu’il en était. Mais avec Go ? Pas vraiment. Lorsque j’ai commencé ce projet en janvier, gdb a échoué sur tous les programmes sur lesquels je l’ai essayé. delve ne fonctionnait pas sous OS X, et le débogage avec print était trop lent et limité. Que faire dans ce cas ?

Créer mon propre débogueur, bien sûr.

godebug

La seule chose qui s’oppose [à un bon débogueur Go] est l’écriture de beaucoup de code de bas niveau non portable communiquant avec des interfaces non documentées et boguées.
Rob Pike

godebug est un autre type de débogueur. Les débogueurs traditionnels pour les langages compilés utilisent des appels système de bas niveau et lisent des fichiers binaires pour rechercher des symboles de débogage. Ils sont difficiles à configurer correctement et difficiles à porter.

godebug adopte une approche différente : il prend le code source d’un programme cible, insère du code de débogage entre chaque ligne, puis le compile et l’exécute à la place. Le résultat est un débogueur entièrement fonctionnel et extrêmement portable. En fait, grâce à gopherjs, vous pouvez l’exécuter directement ici dans votre navigateur !

Vous pouvez modifier le programme et le relancer avec le bouton « DEBUG IT ! » autant de fois que vous le souhaitez.

Comment cela a-t-il fonctionné ?

Voici un schéma rapide de la démo ci-dessus :

Le code d’origine est transformé deux fois. Tout d’abord, godebug insère l’instrumentation de débogage. Ensuite, gopherjs compile le résultat en JavaScript.

Examinons l’étape d’instrumentation. (Pour en savoir plus sur la partie gopherjs (qui est géniale), consultez son site web.) Voici quelques-uns des appels que godebug insère :

  • godebug.EnterFunc indique à la bibliothèque d’exécution de godebug que nous entrons dans une fonction. Puisque la commande « next » ne s’arrête pas à l’intérieur des appels de fonction, la bibliothèque d’exécution prend note de ces appels pour savoir quand ignorer des lignes.
  • godebug.ExitFunc indique à la bibliothèque d’exécution que nous quittons une fonction. Omis dans main.
  • godebug.Line met le programme en pause et attend une saisie si, et seulement si, une commande utilisateur ou un point d’arrêt le lui a demandé. Lorsqu’il est en pause, il demande une saisie et répond à toutes les commandes.
  • godebug.Declare enregistre la correspondance entre les noms des variables et leurs valeurs. Cette correspondance est utilisée par la commande print.

Il s’agit d’un aperçu abrégé. Il y a d’autres fonctions que godebug insère, et de nombreux détails concernant les fonctions ci-dessus ont été omis. Mais ce sont les éléments de base du fonctionnement de godebug.

Utiliser godebug

Tout ce qui précède (moins la partie serveur et JavaScript) est regroupé dans l’outil de ligne de commande godebug. Voici comment l’utiliser :

Étape 1. Installation

$ go get -u github.com/mailgun/godebug

Étape 2. Définir des points d’arrêt

Ajoutez ce marqueur partout où vous souhaitez un point d’arrêt :

_ = "breakpoint"

Cette instruction devient un point d’arrêt lorsqu’elle est exécutée sous godebug, et n’a aucun effet sinon.

Puisque les points d’arrêt font partie du code source, vous pouvez les entourer de votre propre logique. Disons que vous exécutez un test piloté par un tableau avec des dizaines de cas, et que l’un d’eux échoue : celui qui a testé l’entrée \"weird string\". Vous pouvez ajouter ce point d’arrêt à votre test :

for _, tt := range myTestCases { if tt.in == "weird string" { _ = "breakpoint" } ... }

godebug test mettra le programme en pause à l’instruction du marqueur, idéalement placée juste avant l’exécution du cas de test qui échoue.

Étape 3. Exécuter votre programme

Utilisez la commande godebug run :

godebug run

Ou, pour les tests, utilisez la commande godebug test :

godebug test

Par défaut, godebug n’ajoutera l’instrumentation de débogage qu’au package main (pour godebug run) ou au package en cours de test (pour godebug test). Il n’instrumentera aucun package importé. Cela permet de réduire la charge du débogueur : tous les packages qui ne vous intéressent pas s’exécuteront normalement, à pleine vitesse.

Cela signifie que par défaut, vous ne pouvez pas entrer dans les appels de fonction depuis des packages importés. Mais il vous arrivera parfois d’en avoir besoin ! Pour déboguer d’autres packages, passez l’indicateur -instrument à godebug run ou godebug test :

godebug test -instrument=pkgA,pkgB,pkgC pkg/under/test

La commande ci-dessus instrumentera (et vous permettra ainsi d’entrer dans) pkgApkgBpkgC et pkg/under/test. Elle compilera et exécutera ensuite les tests pour pkg/under/test. Une logique similaire s’applique pour godebug run.

À vous d’essayer !

La prochaine fois que vous voudrez comprendre ce qui se passe dans un programme Go, essayez godebug. Gardez à l’esprit qu’il s’agit encore d’un outil récent qui a besoin d’être perfectionné. Plus particulièrement, certaines de ses limitations connues sont les suivantes :

  • impact sur les performances
  • peut causer des conflits de lecture si votre programme lit depuis stdin
  • impossibilité de s’attacher à un processus en cours d’exécution
  • obligation de connaître les packages que vous souhaitez déboguer avant de démarrer la session

Cela dit, je suis ravi de cet outil et j’espère qu’il apportera beaucoup de valeur à la communauté Go. Essayez-le et dites-moi ce que vous en pensez ! Si vous rencontrez des problèmes, n’hésitez pas à m’en faire part. Signalez un problème sur https://github.com/mailgun/godebug/issues ou envoyez un email à : dev@godebug.rocks

En espérant qu’il vous plaise !

https://github.com/mailgun/godebug

Vous souhaitez en savoir plus sur godebug ? Voici une présentation que j’ai donnée à GoSF, abordant plus en détail la génération de code et la gestion de la concurrence :