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