04 September 2006

Язык erlang: Трассирование вызовов функции -- пошагово

Трассирование процессов в Erlang



Трассирование процессов -- Зачем?


Иногда, если программа на языке erlang вылетает с ошибкой (скажем, badmatch), то нужно понять, откуда берется эта ошибка и при каких входных данных. Зачастую при этом пользоватся дебаггером проблематично -- либо очень большое количество вызовов, либо хочется так-же отловить вызовы многих функций в модуле.

Трассирование процессов -- Как?


Из шелла, где запущена программа, или прямо в коде программы нужно добавить следующие команды.

dbg:tracer(),
dbg:p(new, c),
dbg:tpl(module_name, [{'_',[],[{return_trace}]}]),



Трассирование процессов -- Детали


Первая строчка запускает собственно трассировщик, ее нужно один раз в течении работы программы.
Вторая строчка указывает, что мы хотим трассировать и в каких процессах.
Первый аргумент dbg:p -- какие процессы мы хотим трассровать

  • Pid (скажем self() или любой другой pid) -- только вызовы функций, которые будут делаться указанным процессом

  • new -- только новосоздаваемые процессы, уже существующие процессы трассироваться не будут

  • existing -- будут трассироваться только уже существующие процессы

  • all -- трассировать все процессы в системе -- существующие и новосоздаваемые.



второй аргумент -- обозначает, что трассировать. Самые интересные значения:

  • c -- вызовы функций

  • m -- поученные процессом сообщения

  • [c,m] -- и то и другое



Третья строчка -- это 50% магии данного совета -- из какого модуля именно трассировать функции и что делать с этим трейсом.
dbg:tpl бывает с разным arity - 2,3,4. Нас интересуют варианты с арити 2 и 3
dbg:tpl(Module, MatchSpec) и dbg:tpl(Module, Function, MatchSpec).

MatchSpec -- для того что бы получить распечатку трассировщика на консоли нужно указывать именно
[{'_',[],[{return_trace}]}]

в первом варианте - с 2 аргументами, трассироваться будут все функции модуля,
а во втором варианте -- будут трассироваться только функции с данным именем.

Трассирование процессов -- Пример


Вот пример трассировки функции erlang:date

1> dbg:tracer().
{ok,<0.34.0>}
2> dbg:p(all, c).
{ok,[{matched,nonode@nohost,26}]}
3> dbg:tpl(erlang, date, [{'_',[],[{return_trace}]}]).
{ok,[{matched,nonode@nohost,1},{saved,1}]}
4> erlang:date().
(<0.32.0>) call erlang:date()
{2006,9,4}(<0.32.0>) returned from erlang:date/0 -> {2006,9,4}


Если включена трассировка функций всего модуля и функция делает вызовы к локальным функциям модуля -- то вы увидете аргументы и возвращаемые значения вызываемых функций.

No comments: