Jul/090
Traces
Avant de pouvoir commencer les développements Erlang, il est intéressant de savoir comment « débuguer » (!!! pfff) et générer des traces.
Comme pour les autres fonctions Erlang, il peut être consommateur de temps de trouver les informations nécessaires.
Pour les traces, un système « simple » et immédiat sera de tracer les informations dans la console, via le shell.
Débuguer
Pour cela, Erlang fournit le module dbg
. Ce dernier permet de définir déclarativement les fonctions qui seront prises en charge par le serveur de trace.
Démarrez le serveur :
rake start
Appuyez sur Entrée, afin d’afficher le prompt du shell Erlang. Démarrez un serveur de debugage sur le nœud local.
> dbg:tracer(). {ok,<0.57.0>}
Pour un peu d’aide, on peut taper :
> dbg:h().
Il est nécessaire alors de modifier les options permettant d’indiquer ce qui sera tracé ou non, grâce à la méthode p()
(oui, ils sont forts pour trouver des noms compréhensibles) :
> dbg:p(all, c).
Ici, on demarre la trace pour tous les appels (call
) de tous les processus (all
), Différentes options sont disponibles, comme :
- s (send)
- r (receive)
- c (call)
- p (process)
- all
- clear
- …
Ces options peuvent être combinées dans une liste.
Enfin, il faut définir les expressions que l’on veut tracer :
> dbg:tpl(ercm_web, loop, []).
Ici, on affiche les appels à la méthode loop()
du module web. Donc, Tout accès à une URL sera tracé, comme ci dessous :
> (<0.56.0>) call ercm_web:loop({mochiweb_request,#Port<0.928>,'GET',"/test", {1,1}, {8, {"host", {'Host',"localhost:8000"}, {"accept", {'Accept',"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}, nil, {"accept-language", {'Accept-Language',"en-us,en;q=0.5"}, {"accept-encoding", {'Accept-Encoding',"gzip,deflate"}, {"accept-charset", {'Accept-Charset',"ISO-8859-1,utf-8;q=0.7,*;q=0.7"}, nil,nil}, nil}, {"connection",{'Connection',"keep-alive"},nil,nil}}}, {"user-agent", {'User-Agent',"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.1) Gecko/20090718 Shiretoko/3.5.1"}, {"keep-alive",{'Keep-Alive',"300"},nil,nil}, nil}}}},"/d/apps/ercm/priv/www")
Codes retour
Si l’on ne veut que le code retour, cela se complique encore un peu .
Il faut toujours utiliser la méthode de template vue précédemment, mais en ajoutant une fonction de « matching ».
Le code retour de la méthode loop/2
est défini ainsi :
dbg:tpl(ercm_web, loop, dbg:fun2ms(fun(_) -> return_trace() end)).
Je n’affiche pas le résultat d’une telle commande ici, car c’est beaucoupp trop long.
La méthode return_trace()
n’existe pas dans le module dbg
, et elle ne peut être utilisée que dans la fonction fun2ms
et uniquement dans le shell !!!
En fait, il s’agit d’un alias pour les spécifications de correspondance (match_spec) suivantes :
[{'_', [], [{return_trace}]}]
Je n’ai pas encore assimilé complètement le concept, mais d’après la doc, il s’agit d’un équivalent à une fonction, mais compilé et interprété par le runtime de façon beaucoup plus efficace (et plus limitée).
Les 3 parties du code précédent correspondent aux termes « HEAD », « CONDITION » et « BODY ».
- HEAD = ‘_’ : matche tous les éléments
- CONDITION = [] : Aucune condition particulière
- BODY = return_trace : une des fonctions d’action possible, voir la doc pour les autres
Donc ici - si on résume en français - pour tous les appels a loop()
, on exécute le message return_from
vers la fonction.
On peut donc définir des éléments de trace automatiques, de la façon suivante (dans la méthode loop/2
du module ercm_web
) :
"/" ++ Path = Req:get(path), case Path of "trace" -> dbg:tracer(), dbg:p(all, c), dbg:tpl(?MODULE, loop, [{'_', [], [{return_trace}]}]), Req:ok({"text/plain", [], ["trace on"]}); _ -> true end,
Ceci permet de déclencher les traces vues précédemment grâce à l’url http://localhost:8000/trace
.
Pas vraiment utile comme fonctionnement, mais c’est pour l’exemple. Ces informations seront réexploitées ultérieurement.