Я пытаюсь начать использовать erlang:trace/3 и dbg модуль для трассировки поведения живой производственной системы, не удаляя сервер.
Документация непрозрачна (мягко говоря) и онлайн, кажется, нет никаких полезных учебных руководств.
То, что я потратил весь день попытку сделать, было получить то, что происходило в конкретной функции путем попытки применить трассировку к module:function с помощью dbg:c и dbg:p, но без успеха вообще...
У кого-либо есть сжатое объяснение того, как использовать трассировку в живой системе Erlang?
Основные шаги трассировки вызовов функций находятся на неживом узле:
> 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.
Можно трассировать несколько функций одновременно. Добавляйте функции, вызывая tp
для каждой функции. Если необходимо отследить неэкспортируемые функции, необходимо вызвать tp
. Для удаления функций необходимо аналогичным образом вызвать ctp
или ctpl
. Некоторые общие вызовы tp:
> 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.
Последним аргументом является спецификация соответствия. Вы можете поиграть с этим, используя dbg:fun2ms
.
Вы можете выбрать процессы, которые будут отслеживаться при вызове в p(). Элементы описаны в разделе erlang:trace. Некоторые вызовы:
> 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
Думаю, вам никогда не понадобится напрямую вызывать erlang:trace
, так как dbg
делает практически все за вас.
Золотое правило для живого узла - генерировать в оболочку только количество выводимых трасс, что позволяет набирать dbg:stop_clear().
. :)
Я часто использую трассировщик, который автоматически останавливается после ряда событий. Например:
dbg:tracer(process, {fun (_,100) -> dbg:stop_clear();
(Msg, N) -> io:format("~p~n", [Msg]), N+1 end, 0
}).
Если вы ищете отладку на удаленных узлах (или нескольких узлах), ищите pan
, eper
, inviso
или onviso
.
Модуль 'dbg' - это довольно низкоуровневый материал. Есть два хака, которые я очень использую для часто необходимых мне задач.
Используйте код расширения командной строки / оболочки Erlang на http://www.snookles.com/erlang/user_default.erl . Первоначально он был написан (насколько мне известно) Сержем Алейниковым, и был полезным примером, «вот как я добавляю пользовательские функции в оболочку». Скомпилируйте модуль и отредактируйте файл ~ / .erlang, указав его путь (см. Комментарий вверху файла).
Используйте утилиту « redbug », которая входит в набор утилит EPER . Использовать dbg для создания миллионов событий трассировки очень просто. за несколько секунд. Выполнение в производственной среде может иметь катастрофические последствия. Для использования в разработке или производстве redbug делает практически невозможным уничтожение работающей системы из-за перегрузки, вызванной трассировкой.
В реальных системах мы редко отслеживаем до оболочки. Если система правильно настроена, значит, она уже собирает ваши журналы Erlang, которые были напечатаны в оболочке. Мне не нужно подчеркивать, почему это важно для любого живого узла ...
Позвольте мне подробнее рассказать о трассировке до файлов:
Возможна трассировка до файла, что даст двоичный результат, который может быть преобразован и проанализирован позже . (для дальнейшего анализа или автоматизированной системы управления и т. д.)
Примером может быть:
Трассировка нескольких файлов в оболочке (12x50 Мбайт). Пожалуйста, всегда проверяйте доступное дисковое пространство перед использованием такой большой трассировки!
dbg: tracer (порт, dbg: trace_port (файл, {"/ log / trace", wrap, atom_to_list (node ()), 50000000,12})).
dbg: p (все, [звонок, отметка времени, return_to]).
При этом давайте посмотрим на базовую последовательность команд трассировки:
<1> dbg: stop_clear ().
<2> dbg: tracer ().
<3> dbg: p (все, [звонок, отметка времени]).
<4> dbg: tp (...).
<5> dbg: tpl (...).
<42> dbg: stop_clear ().
Вы можете:
добавить триггеры, определив некоторые функции fun () в оболочке, чтобы остановить трассировку в заданное время или событие. Рекурсивные fun () - лучше всего подходят для этого, но будьте очень осторожны при их применении.
применяют огромное количество сопоставлений с образцом, чтобы гарантировать, что вы отслеживаете только определенный процесс с конкретным вызовом функции с конкретным типом аргументов ...
У меня была проблема некоторое время назад, когда нам нужно было проверить содержимое таблицы ETS и при появлении определенной записи мы должны были остановить трассировку в течение 2-3 минут.
Я также предлагаю книгу «Программирование на Erlang», написанную Франческо Чезарини. ( Программирование на Erlang @ Amazon )