Comment aborder la correction d'un bogue non reproductible / aléatoire?


11

Nous avons un site multilingue dans lequel un bug a été découvert il y a quelques jours. Il affichait d'autres données linguistiques dans une autre langue et le mélange de données comme la langue anglaise était également sélectionné, mais il affichait également des données d'autres langues dans la page et vice-versa. Il le fait rarement mais est présent sur le site Web. Parcourir le code n'aide pas non plus, car cela ne se produit pas toujours.

Une suggestion pour trouver le problème en temps opportun? Je demande des stratégies ici.


4
commencer à sonder le code pour les situations qui permettront à ce bogue de se produire (au lieu de le faire dans l'autre sens)
Imran Omar Bukhsh

Réponses:


20

La première étape consiste à essayer de caractériser ce qui peut provoquer ce type de problème. Comme cela est lié à la sélection de la langue appropriée pour les sections du code, commencez par considérer les éléments suivants:

  • Comment la langue est-elle détectée? Est-ce basé sur les informations de la requête HTTP? Est-il basé sur des informations de session?, Ou est-il basé sur des champs de base de données? En substance, cela peut-il être un problème lié à la façon dont votre application sélectionne la langue pour chaque section?
  • Comment la langue est-elle affichée? Tirez-vous d'un fichier de propriétés ou d'une base de données? Est-il possible que la référence à la langue correcte se perde? La langue mélangée que vous voyez est-elle toujours la valeur par défaut pour le site?
  • Y a-t-il une corrélation avec l'environnement client? Ceci est lié à la première puce, mais va un peu plus loin. J'ai rencontré d'étranges problèmes de rendu en raison de proxys de mise en cache en aval. En général, ces types de problèmes sont une page entière qui est périmée ou qui sert la page d'une personne à d'autres utilisateurs (ce qui était embarrassant).
  • Utilisez-vous une valeur Thread Local? Si une demande est traitée sur plusieurs threads, la valeur locale du thread aura des informations différentes en fonction du thread qui fonctionne à ce moment. Dans un environnement de serveur Web, vous ne pouvez pas supposer que le thread sur lequel vous avez commencé le traitement sera le même thread que celui sur lequel vous avez terminé le traitement, sauf si cela fait partie des spécifications de votre plate-forme. Les rédacteurs de serveurs ont découvert que s'ils réutilisent un petit groupe de threads et que le travail de multiplexage leur est effectué en morceaux, ils peuvent gérer plus de demandes simultanément. Même si vous avez un thread du début à la fin d'une demande, le serveur peut multiplexer d'autres requêtes sur ce thread en même temps. Au lieu des sections locales de thread, envisagez de lier cette valeur aux attributs de demande ou de session.

Maintenant, une fois que vous avez caractérisé les possibilités de ce qui peut mal tourner, il est temps de vous assurer que vous disposez des données dont vous avez besoin pour essayer de découvrir ce qui a mal tourné.

  • Utilisez une journalisation abondante autour des zones à problème. C'est un endroit où un outil comme Log4J ou Log4Net peut vraiment briller. Ce cadre de journalisation, et d'autres similaires, vous permet d'activer la journalisation pour certaines catégories tout en réduisant le bruit pour tout le reste - tout en modifiant un fichier de configuration. Vous souhaitez introduire de nouvelles instructions de journalisation pour déterminer si ce que vous soupçonnez pourrait être le problème. Assurez-vous également que vos journaux d'accès HTTP contiennent toutes les informations que vous souhaitez sur chaque demande (cookies, paramètres d'en-tête http, etc.)
  • Essayez de simuler le problème. Étant donné que cela se produit sporadiquement, à quoi ressemble la charge sur le serveur au moment où elle se produit? Êtes-vous frappé par un certain nombre de demandes simultanées provenant d'un mélange de langues? Si tel est le cas, essayez de simuler ce type de charge dans votre environnement de test. Un outil similaire à JMeter pourrait être ce dont vous avez besoin. Vous voudrez également pouvoir usurper des adresses IP pour vos faux clients. N'oubliez pas que les adresses IP sont divisées afin que vous puissiez déterminer le pays / la région sur lequel l'IP est basé sur les deux premiers segments de l'adresse.
  • Le problème sera tout aussi sporadique dans votre environnement de test, mais en vous restreignant à votre véritable cause, vous pouvez fausser les résultats pour que cela se produise plus souvent que dans la nature. De plus, vous pouvez plus facilement consulter les fichiers journaux et essayer d'en tirer des leçons.
  • C'est un processus itératif, alors soyez patient. Vous devez induire le type de charge que vous pensez va reproduire le bug, consultez les journaux, et d' affiner vos tests basés sur ce que vous trouvez. L'important est d' identifier le problème , alors résistez à l'envie de faire quelques correctifs simples qui pourraient ne faire que le vrai problème se produire moins souvent.

Enfin, une fois que vous avez réduit le problème au point où vous savez comment le reproduire et ce qui en est la cause, écrivez le plus petit test automatisé possible pour forcer le problème dans le code. Si vous avez limité le problème à une classe ou à une paire de classes qui ne fonctionnent pas correctement, reproduisez-le à ce niveau. Vous ne devriez pas avoir à générer 100 threads pour le faire, faites simplement le plus petit test qui peut provoquer le problème à 100% du temps.

Vous pouvez maintenant le réparer et être raisonnablement sûr qu'il ne reviendra pas vous mordre à nouveau.


10

Le bug n'est pas irréproductible. Vous n'avez tout simplement pas encore découvert comment le reproduire.

Aucun bogue n'est aléatoire, à moins que vous ne lançiez une exception basée sur la valeur de retour d'une instruction Random ().

Je sais que cela peut sembler sémantique, mais c'est rassurant mentalement de se le dire.

Il est très difficile et frustrant de savoir comment reprocher un bug qui ne se produit qu'en raison de conditions de course complexes ou autres.

Quant à savoir comment le trouver, j'activerais / ajouterais une journalisation à l'application dans des endroits qui pourraient vous donner plus d'informations.

Dites ensuite aux personnes qui voient le bogue (qu'il s'agisse de développeurs, d'AQ, d'utilisateurs finaux) de signaler dès qu'ils le voient l'heure à laquelle il s'est produit, puis consultez vos journaux. Demandez-leur d'autres informations ainsi que le bug ne peut se produire qu'en raison de l'interaction de plusieurs systèmes différents ou en raison d'une condition de concurrence

J'espère que vous pourrez trouver une piste.


même les appels Random () ne sont vraiment aléatoires que s'ils sont dérivés d'un générateur de bruit blanc matériel. Ils sont pseudo-aléatoires, ce qui signifie que les nombres sont distribués mathématiquement dans un ordre aussi aléatoire que possible. Mais si vous partez de la même valeur "seed", vous obtiendrez la même réponse à chaque fois.
Berin Loritsch

1
@Berin: Je sais.
Gilles

+1 pour "vous n'avez pas encore découvert comment le reproduire". Tous les bogues ont une cause racine, sinon ils ne se produiraient pas.
Mike S

1
Il ne doit pas nécessairement être hors Random (), les choses qui dépendent du temps, en particulier celles impliquant un accès incorrect à une ressource partagée peuvent être très difficiles à reproduire.
Loren Pechtel

2
@ Gilles: Sauf qu'ils peuvent ne pas être déterministes sur tout ce que vous pouvez raisonnablement mesurer. (Disons, exactement quand une autre tâche est sortie, c'est la tranche de temps.)
Loren Pechtel

5

Vous pouvez essayer de trouver des endroits dans votre code où vous pouvez reconnaître que le problème est survenu (paramètres incohérents dans une méthode par exemple), ajouter les vérifications à votre code et les laisser ajouter des informations supplémentaires au journal de débogage (comme une trace de pile, des objets ajouté à la session, etc.)

En faisant cela avec un peu de chance, vous pouvez capturer des informations sur les événements et déduire votre chemin vers le problème.


2

L'automatisation devrait aider, si ce sont les mêmes étapes pour reproduire qui échouent parfois, automatiser cela et le mettre en boucle. Exécutez 50 000 fois et il est très probable que cela se produise.


L'événement n'est pas aléatoire, il semble juste aléatoire. Faire cela peut le faire apparaître, mais vous donnera très peu d'informations sur la raison pour laquelle il est apparu.
Josh K

1
@Josh - S'il n'est pas en mesure de le reproduire, cela peut être un bon moyen de le faire et d'obtenir une trace de pile avec des symboles de débogage, par exemple. Je pense que c'est un excellent premier pas - à voir de
visu

Vous supposez qu'il existe une pile et qu'elle peut être obtenue. Il ne nous a donné aucune information technique sur l'application ou sur son accessibilité pour le débogage sous ce type de charge. Ce n'est pas une stratégie de débogage , c'est la frapper avec un marteau essayant d'attraper le moment exact où elle se casse.
Josh K

@Josh - mon expérience du monde réel me dit que la chose la plus précieuse pour enquêter / corriger un bug est de le voir de première main. Que ce soit quelque chose avec le timing que vous pouvez voir, une trace de pile, quelque chose dans les journaux ou autre chose. Dans la mesure du possible, avoir testé des problèmes apparemment aléatoires dans une boucle m'a permis d'y arriver très rapidement. Si vous avez une idée différente, postez-la comme une réponse pour l'amour du Christ - c'est une méthode valide et une réponse valide.
Kieren Johnstone

Je ne suis pas d'accord et je pense que la réponse de Berin est la bonne façon de résoudre ce problème.
Josh K

1

essayez de trouver des modèles pour identifier les conditions qui provoquent ce problème. Cela devrait vous diriger vers les sections de votre code qui échouent (ou se comportent de manière incohérente).


No shit ..............
theringostarrs

0

Pouvez-vous détecter le moment où le problème se produit? Si oui, pouvez-vous vider de manière fiable des informations sur l'état du système à ce stade?

Si la réponse à ces deux questions est oui, instrumentez votre code pour enregistrer autant d'informations que possible lorsque l'erreur se produit réellement, puis attendez.

Ce n'est pas un remplacement de ce que d'autres ont suggéré (vous devrez toujours expliquer comment le code peut entrer dans l'état que vous voyez), mais tant que vous ne pouvez pas reproduire le bogue à volonté, c'est une bonne idée de ne pas perdre les occasions où cela apparaît.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.