Использование трассировки и 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( ... ).

  • Как видно из ответа Zed.

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

  • Как видно из ответа Zed.

< 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 делает почти невозможным убить запущенную систему с вызванной трассировкой перегрузкой.