Quand un utilisateur clique sur le bouton de signalement, il se passe beaucoup de choses qu'il ne voit jamais. Voici tout ce qui est capturé, et pourquoi chaque élément est là.
Les logs de console, passé compris
Le plus évident, avec un détail qui l'est moins : BugDump capture les logs d'avant l'ouverture du widget.
Cela compte plus qu'il n'y paraît. Dans un vrai rapport de bug, la séquence n'est presque jamais « l'erreur se produit, l'utilisateur la signale aussitôt ». C'est plutôt : l'erreur se produit, la page entre dans un état subtilement cassé, l'utilisateur essaie encore trois choses, s'y perd, et signale le problème quatre minutes plus tard.
Un collecteur qui démarre au moment du rapport capture ces quatre minutes de confusion et rate l'erreur qui les a causées. Le SDK installe son collecteur de console à l'initialisation, si bien que l'erreur d'origine est toujours là quand le rapport finit par être envoyé.
Les requêtes réseau
Méthode, URL, statut, timing. C'est là que se trouvent la plupart des bugs : pas dans votre code frontend, mais dans la réponse que votre frontend a reçue.
Les corps de requête et de réponse sont disponibles via captureNetworkBodies, et ils sont désactivés par défaut. Ce choix est délibéré. Les corps sont l'endroit où des jetons d'authentification, des données personnelles et des informations de paiement risquent le plus d'apparaître. Les activer devrait être une décision que vous prenez, pas un réglage par défaut dont vous héritez.
Même sans les corps, les codes de statut et les timings résolvent la plupart des bugs. Un 500 juste avant que l'utilisateur abandonne, c'est votre bug. Un 200 qui a pris neuf secondes, c'est aussi votre bug, et votre outil de suivi d'erreurs ne l'a jamais signalé.
Les captures d'écran, et l'outil Flou
Les captures d'écran existent en deux variantes, et le compromis mérite d'être compris.
screen-capture utilise getDisplayMedia. Le rendu est exact au pixel près : canvas, vidéo, iframes cross-origin, listes déroulantes natives, tout est capturé exactement tel qu'affiché. Le prix à payer, c'est une boîte de dialogue d'autorisation du navigateur.
dom fait le rendu à partir du DOM avec html2canvas. Pas de demande d'autorisation, donc pas de friction, mais le contenu des canvas et les iframes cross-origin peuvent ne pas survivre.
BugDump utilise screen-capture par défaut et se rabat automatiquement sur dom quand l'utilisateur refuse l'autorisation. Un refus doit dégrader la capture, pas faire perdre le rapport.
Vient ensuite l'annotation : flèche, rectangle, dessin à main levée, texte et flou. C'est l'outil Flou qui mérite qu'on s'y arrête, parce que c'est un contrôle de confidentialité déguisé en outil de dessin. Le masquage a lieu dans le navigateur : une zone floutée n'est jamais envoyée. Des utilisateurs qui n'auraient pas envoyé la capture d'une page contenant des données clients peuvent désormais le faire.
La relecture de session
Un enregistrement rrweb du DOM dans le temps. Pas une vidéo : une relecture du document réel, que vous pouvez inspecter.
La relecture mérite sa place pour la catégorie de bugs où la console est propre, le réseau est propre, et l'utilisateur est absolument certain que quelque chose a cassé. En général, il a raison, et en général, ce qu'il a fait n'est pas ce qu'il a décrit. La relecture vous montre la différence.
Les actions
Clics, saisies et navigation, dans l'ordre.
C'est le signal le plus modeste et l'un des plus utiles, parce que ce sont vos étapes de reproduction, enregistrées plutôt que remémorées. « Étapes de reproduction » est le champ que les utilisateurs remplissent le plus mal, et celui dont vous avez le plus besoin. Alors j'ai arrêté de le demander, et je l'enregistre.
Les notes vocales
Certains utilisateurs n'écriront pas trois phrases, mais parleront volontiers pendant vingt secondes. L'agacement porte aussi une information que le texte aplatit : on entend quelle partie du parcours les a vraiment fait craquer.
Les mesures de performance
Temps de chargement de la page et des ressources, pour les rapports qui parlent en réalité de lenteur. « L'appli est lente » est un vrai rapport de bug, et sans mesures, c'est un rapport qu'on ne peut ni confirmer ni réfuter.
Les métadonnées
Navigateur, OS, taille du viewport, URL de la page, horodatage.
Le viewport est l'atout caché. Une part étonnante des rapports « le bouton ne marche pas » sont des bugs de mise en page à une largeur que personne n'a testée. Les utilisateurs ne pensent presque jamais à mentionner la taille de leur fenêtre. C'est un seul nombre, il est capturé automatiquement, et il règle une catégorie de bugs qui serait sinon vraiment difficile à reproduire.
Ce que je ne fais pas, volontairement
Je n'exige pas l'identité de la personne qui signale. Le nom et l'e-mail sont dans une section repliée. Un rapport sans nom reste un rapport ; un formulaire qui exige une identité en reçoit moins.
Je n'exige ni titre, ni catégorie, ni gravité, ni priorité. Ce sont des champs de tri déguisés en champs de rapport. Les utilisateurs les devinent, se trompent, et vous refaites le tri de toute façon. Le seul champ obligatoire est la description.
Le widget ne déborde pas sur votre page. Il s'affiche dans un Shadow DOM. Votre CSS ne peut pas l'atteindre, et son CSS ne peut pas vous atteindre.
Le principe
Chaque signal ici suit une seule règle : si le navigateur le sait déjà, l'utilisateur ne devrait pas avoir à le dire.
Le travail de l'utilisateur, c'est une phrase sur ce qu'il attendait. Tout le reste, c'est mon travail, et le navigateur en a déjà fait l'essentiel.
Pour aller plus loin
Comment capturer les logs console et les requêtes réseau d'un utilisateur — instrumenter la console, les erreurs, fetch et XHR sans casser la page qu'on surveille.
La relecture de session sans la surveillance — une relecture limitée à un rapport, que l'utilisateur peut flouter et que vous coupez en une ligne.
Un modèle de rapport de bug qui marche vraiment (et comment l'automatiser) — les champs que seul un humain peut remplir, et ceux qu'une machine remplit mieux.