Эрланг: Есть ли лучший способ определить, находится ли что-то в стеке, чем регулярное выражение в трассировке стека? - PullRequest
1 голос
/ 15 сентября 2011

Проект, над которым я работаю, имеет множество встроенных механизмов телеметрии и отладки, которые должны быть доступны в релизе, но НЕ ДОЛЖНЫ использоваться большинством частей системы.Я хотел бы создать макрос, который будет вызываться в верхней части таких методов, который вызовет исключение, если метод не был вызван из одного из очень ограниченных групп модулей.

Например,У меня есть модуль отладки, который я могу использовать для управления состоянием системы из консоли, и у меня есть веб-инструмент, который позволяет администраторам проверять и изменять систему.Некоторые из методов, которые предназначены для их потребления (но реализованы в модулях по всей системе), хороши для случайного использования, но могут нанести ущерб, если кто-то допустил ошибку, назвав их частью нормальной работы.

РЕДАКТИРОВАТЬ: я попробовал списки: предложение ключевого слова, ниже, и это работает для любого модуля, который я могу явно назвать, который, вероятно, является лучшим, что я когда-либо собирался управлять.У меня есть модули, такие как web_foo, web_bar, web_foo_other, web_yippie_ki_yea_mf, которые соответствуют тому, что я использую регулярные выражения для.

Я могу сделать что-то вроде следующего.( Я не скомпилировал это. Я надеюсь, что любые ответы, которые вы дадите, помешают мне когда-либо запустить это в производство. =] )

try
  %gotta do this to get the stacktrace:
  throw(a)
catch
  _ -> 
    Stack = erlang:get_stacktrace(),
    {_, RegExp} = re:compile("webmanager", [multiline]),
    case Match = re:run(Stack, RegExp) of
      nomatch ->
        throw(im_sorry_dave__im_afraid_i_cant_do_that);
      {match, _} ->
        ok
    end
end

Ответы [ 2 ]

3 голосов
/ 15 сентября 2011

Поскольку Stack - это список кортежей, представляющих вызовы методов, вы можете использовать lists:keysearch(webmanager, 1, Stack), чтобы проверить, находится ли модуль в трассировке стека.

1 голос
/ 16 сентября 2011

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

-module(adm_facade).
-export([register_admin_mode_proc/0,
         unregister_admin_mode_proc/0,
         adm1/1
       ]).

register_admin_mode_proc() ->
    register(admin_mode_proc, self()).

unregister_admin_mode_proc() ->
    unregister(admin_mode_proc).

adm(X) ->
    check_adm(),
    some_other_module:adm(X).

check_adm() ->
    Caller = self(),
    case erlang:whereis(admin_mode_proc) of
        Caller -> ok;
        _ -> erlang:error({access_denied, Caller})
    end.

Конечно, это ограничивает функции администратора одним абонентом, но вы можете использовать gproc или вашего собственного регистратора.

...