Использование трассировки и dbg в Erlang
Я пытаюсь начать использовать erlang: trace/3 и модуль dbg для отслеживания поведения живой производственной системы, не опуская сервер.
Документация непрозрачная (мягко говоря), и, как представляется, нет никаких полезных обучающих программ в Интернете.
То, что я потратил весь день на то, чтобы попытаться сделать, это захватить то, что происходило в определенной функции, пытаясь применить трассировку к модулю: функция с использованием dbg: c и dbg: p, но без успеха вообще...
Есть ли у кого-нибудь краткое объяснение того, как использовать трассировку в живой системе Erlang?
Ответы
Ответ 1
Если вы предпочитаете графический трассировщик, попробуйте erlyberly. Он позволяет вам выбирать функции, которые вы хотите отслеживать (во всех процессах на данный момент) и имеет дело с API-интерфейсом dbg.
Однако он не защищает от перегрузки, поэтому не подходит для производственных систем.
![enter image description here]()
Ответ 2
Основные этапы трассировки вызовов функций приведены в неживом node:
> 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
для каждой функции. Если вы хотите отслеживать неэкспортируемые функции, вам нужно вызвать tpl
. Чтобы удалить функции, вызовите 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
делает для вас почти все.
Золотое правило для живого node состоит в том, чтобы генерировать только количество выходных данных трассировки в оболочку, что позволяет вводить 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
.
Ответ 3
В живых системах мы редко следим за оболочкой.
Если система настроена правильно, она уже собирает ваши журналы Erlang, которые были напечатаны в оболочке. Мне не нужно подчеркивать, почему это важно для любого живого node...
Позвольте мне подробнее остановиться на файлах:
Можно отслеживать файл, который будет генерировать двоичный вывод, который может быть преобразован и проанализирован позже. (для дальнейшего анализа или автоматизированной системы управления и т.д.)
Примером может быть:
-
Отслеживание нескольких упакованных файлов (12x50 Мбайт). Пожалуйста, всегда проверяйте доступное дисковое пространство перед использованием такой большой трассы!
dbg:tracer(port,dbg:trace_port(file,{"/log/trace",wrap,atom_to_list(node()),50000000,12})).
dbg:p(all,[call,timestamp,return_to]).
- Всегда проверяйте тест node перед тем, как вносить что-либо в живую оболочку node!
- Рекомендуется сначала протестировать node или реплику node, чтобы попробовать сценарии.
Это означает, что рассмотрим базовую последовательность команд трассировки:
< 1 > dbg:stop_clear().
- Всегда начинайте с очистки портов трассировки и обеспечения того, чтобы предыдущая трассировка не мешала текущей трассе.
< 2 > dbg:tracer().
- Запустите процесс трассировки.
< 3 > dbg:p(all,[call, timestamp]).
- В этом случае мы отслеживаем все процессы и вызовы функций.
< 4 > dbg:tp( ... ).
< 5 > dbg:tpl( ... ).
< 42 > dbg:stop_clear().
- Опять же, чтобы гарантировать, что все следы были записаны на выходе и уклониться от дальнейших неудобств.
Вы можете:
-
добавить триггеры, определив некоторые fun() - s в оболочке, чтобы остановить трассировку в заданное время или событие. Рекурсивное удовольствие() - это лучшее, что можно достичь, но будьте очень осторожны при их применении.
-
применять огромное разнообразие сопоставлений шаблонов, чтобы гарантировать, что вы трассируете только для конкретного процесса с помощью специального вызова функции с определенным типом аргументов...
У меня была проблема некоторое время назад, когда нам приходилось проверять содержимое таблицы ETS и при появлении определенной записи нам приходилось останавливать трассировку в течение 2-3 минут.
Я также предлагаю книгу Erlang Programming, написанную Франческо Чезарини. (Erlang Programming @Amazon)
Ответ 4
Модуль 'dbg' - довольно низкоуровневый материал. Есть два хака, которые я использую очень
часто для задач, которые мне обычно нужны.
-
Используйте код расширения Erlang CLI/shell в http://www.snookles.com/erlang/user_default.erl. Первоначально он был написан (насколько мне известно) Сержем Алейниковым и
был полезен "так, как я добавляю пользовательские функции в оболочку". компилировать
модуль и отредактируйте файл ~/.erlang, чтобы указать на его путь (см. комментарий вверху
файла).
-
Используйте утилиту redbug, которая содержится в EPER набор утилит.
Очень просто использовать "dbg" для создания миллионов событий трассировки за несколько секунд. дела
поэтому в производственной среде может быть катастрофическим. Для разработки или производства,
redbug делает почти невозможным убить запущенную систему с вызванной трассировкой перегрузкой.