web-dev-qa-db-fra.com

Utilisation de trace et dbg dans Erlang

J'essaie de commencer à utiliser erlang: trace/3 et le module dbg pour suivre le comportement d'un système de production en direct sans arrêter le serveur.

Le documentation est opaque (pour le dire légèrement) et il ne semble pas y avoir de tutoriels utiles en ligne.

Ce que j'ai passé toute la journée à essayer de faire était de capturer ce qui se passait dans une fonction particulière en essayant d'appliquer une trace à module: function en utilisant dbg: c et dbg: p mais sans succès du tout ...

Quelqu'un a-t-il une explication succincte de la façon d'utiliser la trace dans un système Erlang en direct?

65
Gordon Guthrie

Si vous préférez un traceur graphique, essayez alors erlyberly . Il vous permet de sélectionner les fonctions que vous souhaitez tracer (sur tous les processus pour le moment) et traite de l'API dbg.

Cependant, il ne protège pas contre les surcharges et n'est donc pas adapté aux systèmes de production.

enter image description here

7
Andy Till

Les étapes de base du suivi des appels de fonction se trouvent sur un nœud non actif:

> dbg:start().   % start dbg
> dbg:tracer().  % start a simple tracer process
> dbg:tp(Module, Function, Arity, []).   % specify MFA you are interested in
> dbg:p(all, c).   % trace calls (c) of that MFA for all processes.

... trace here

> dbg:stop_clear().   % stop tracer and clear effect of tp and p calls.

Vous pouvez tracer plusieurs fonctions en même temps. Ajoutez des fonctions en appelant tp pour chaque fonction. Si vous souhaitez effectuer le suivi des fonctions non exportées, vous devez appeler tpl. Pour supprimer des fonctions, appelez ctp ou ctpl d'une manière similaire. Certains appels tp généraux sont:

> dbg:tpl(Module, '_', []).  % all calls in Module
> dbg:tpl(Module, Function, '_', []).   % all calls to Module:Function with any arity.
> dbg:tpl(Module, Function, Arity, []). % all calls to Module:Function/Arity.
> dbg:tpl(M, F, A, [{'_', [], [{return_trace}]}]).   % same as before, but also show return value.

Le dernier argument est une spécification de correspondance. Vous pouvez jouer avec cela en utilisant dbg:fun2ms.

Vous pouvez sélectionner les processus à suivre avec l'appel à p (). Les éléments sont décrits sous erlang: trace. Certains appels sont:

> dbg:p(all, c).   % trace calls to selected functions by all functions
> dbg:p(new, c).   % trace calls by processes spawned from now on
> dbg:p(Pid, c).   % trace calls by given process
> dbg:p(Pid, [c, m]).  % trace calls and messages of a given process

Je suppose que vous n'aurez jamais besoin d'appeler directement erlang:trace, Car dbg fait à peu près tout pour vous.

Une règle d'or pour un nœud actif est de générer uniquement une quantité de sortie de trace vers le shell, ce qui vous permet de taper dbg:stop_clear().. :)

J'utilise souvent un traceur qui s'arrêtera automatiquement après un certain nombre d'événements. Par exemple:

dbg:tracer(process, {fun (_,100) -> dbg:stop_clear();
                        (Msg, N) -> io:format("~p~n", [Msg]), N+1 end, 0
                    }).

Si vous recherchez le débogage sur des nœuds distants (ou plusieurs nœuds), recherchez pan, eper, inviso ou onviso.

92
Zed

Sur les systèmes en direct, nous suivons rarement Shell. Si le système est bien configuré, il collecte déjà vos journaux Erlang qui ont été imprimés sur le shell. Je n'ai pas besoin de souligner pourquoi cela est crucial dans n'importe quel nœud en direct ...

Permettez-moi d'élaborer sur le traçage des fichiers:

Il est possible de tracer dans un fichier, ce qui produira une sortie binaire qui peut être convertie et analysée plus tard. (pour une analyse plus approfondie ou un système de contrôle automatisé, etc.)

Un exemple pourrait être:

  • Tracez plusieurs fichiers encapsulés (12x50 Mo). Veuillez toujours vérifier l'espace disque disponible avant d'utiliser une si grosse trace!

    dbg:tracer(port,dbg:trace_port(file,{"/log/trace",wrap,atom_to_list(node()),50000000,12})).
    

    dbg:p(all,[call,timestamp,return_to]).

    • Testez toujours sur un nœud de test avant de saisir quoi que ce soit dans le shell d'un nœud actif!
    • Il est conseillé d'avoir un nœud de test ou un nœud de réplique pour essayer les scripts en premier.

Cela dit, regardons une séquence de commandes de traçage de base:

<1> dbg:stop_clear().

  • Commencez toujours par vider les ports de trace et assurez-vous qu'aucun suivi précédent n'interfère avec la trace actuelle.

<2> dbg:tracer().

  • Démarrez le processus de traçage.

<3> dbg:p(all,[call, timestamp]).

  • Dans ce cas, nous suivons tous les processus et les appels de fonction.

<4> dbg:tp( ... ).

  • Comme on le voit dans la réponse de Zed.

<5> dbg:tpl( ... ).

  • Comme on le voit dans la réponse de Zed.

<42> dbg:stop_clear().

  • Encore une fois, c'est pour s'assurer que toutes les traces ont été écrites dans la sortie et pour éviter tout inconvénient ultérieur.

Vous pouvez:

  • ajoutez des déclencheurs en définissant des fun () - s dans le shell pour arrêter la trace à un moment ou un événement donné. Les amusements récursifs () - sont les meilleurs pour y parvenir, mais soyez très prudents lorsque vous les appliquez.

  • appliquer une grande variété de correspondances de motifs pour vous assurer que vous ne tracez que pour le processus spécifique avec l'appel de fonction spécifique avec le type d'arguments spécifique.

J'ai eu un problème il y a quelque temps, quand nous avons dû vérifier le contenu d'une table ETS et à l'apparition d'une certaine entrée, nous avons dû arrêter la trace dans les 2-3 minutes.

Je suggère également le livre Erlang Programming écrit par Francesco Cesarini. ( Programmation Erlang @ Amazon )

22
cdlf

Le module 'dbg' est un truc de bas niveau. Il y a deux hacks que j'utilise très fréquemment pour les tâches dont j'ai généralement besoin.

  1. Utilisez le code d'extension Erlang CLI/Shell sur http://www.snookles.com/erlang/user_default.erl . Il a été écrit à l'origine (pour autant que je sache) par Serge Aleynikov et a été un exemple utile "c'est comme ça que j'ajoute des fonctions personnalisées au Shell". Compilez le module et éditez votre fichier ~/.erlang pour pointer vers son chemin (voir commentaire en haut du fichier).

  2. Utilisez l'utilitaire " redbug " fourni avec la collection d'utilitaires EPER . Il est très facile d'utiliser "dbg" pour créer des millions d'événements de trace en quelques secondes. Cela peut être désastreux dans un environnement de production. Pour le développement ou l'utilisation en production, redbug rend presque impossible de tuer un système en cours d'exécution avec une surcharge induite par des traces.

9