2015-12-13 2 views
1

Я ищу решение для обработки ошибок в erlang.Обработка ошибок Erlang (cowboy)

Основная задача - запустить код в любом контексте ошибки.

например (если это возможно) переопределение регистратора SASL (или любого подобного поведения), что позволит мне выполнить код при возникновении исключений в любой точке системы.

веселит

ответ

2

Вы можете написать свой собственный модуль обратного вызова, который error_logger можно использовать для выполнения рубок. Это только то, что делает sasl (имеет несколько реализаций регистрации, sasl_report_tty_h, sasl_report_file_h и log_mf_hd, см. sasl (application)).

Чтобы написать собственную реализацию, это не так уж сложно, вам просто нужно реализовать модуль обратного вызова gen_event, который поддерживает необходимые события. Вы можете посмотреть на реализациях, которые SASL обеспечивает, очевидно, или лагер или любое другое каротаж приложение обеспечивает, но вот простая реализация:

-module(example_logger). 
-export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2]). 

init(Args) -> 
    io:format("example_logger: init(~p)~n", [Args]), 
    {ok, state} . 

handle_event(Event, State) -> 
    io:format("example_logger:handle_event(~p, ~p)~n", [Event, State]), 
    {ok, State} . 

handle_info(_Request, State) -> 
    {ok, State} . 

handle_call(_Request, _State) -> 
    {error, unimplemented} . 

terminate(_Reason, State) -> 
    {ok, State} . 

Это просто indiscriminating свалка на стандартный вывод, чтобы вы начали, конечно, вы должны посмотреть на error_logger module и gen_event, чтобы получить полное представление о деталях событий и о том, как это работает.

Пример исключения без использования приведенного выше модуля:

1> spawn(fun() -> 1/0 end). 
<0.35.0> 

=ERROR REPORT==== 13-Dec-2015::14:20:39 === 
Error in process <0.35.0> with exit value: {badarith,[{erlang,'/',[1,0],[]}]} 

Теперь, добавив модуль обратного вызова, вы можете видеть, он получает исключение тоже, а также обработчик терминальную:

2> error_logger:add_report_handler(example_logger, args). 
example_logger: init(args) 
ok 
3> spawn(fun() -> 1/0 end).        
example_logger:handle_event({error,<0.26.0>, 
           {emulator,"~s~n", 
            ["Error in process <0.38.0> with exit value: {badarith,[{erlang,'/',[1,0],[]}]}\n"]}}, state) 

=ERROR REPORT==== 13-Dec-2015::14:20:56 === 
Error in process <0.38.0> with exit value: {badarith,[{erlang,'/',[1,0],[]}]} 

<0.38.0> 

Вы можете отключить стандартный обработчик tty, оставив только ваш модуль обратного вызова:

4> error_logger:tty(false).        
ok 
5> spawn(fun() -> 1/0 end). 
<0.41.0> 
example_logger:handle_event({error,<0.26.0>, 
           {emulator,"~s~n", 
            ["Error in process <0.41.0> with exit value: {badarith,[{erlang,'/',[1,0],[]}]}\n"]}}, state) 
6> 

Ваш модуль обратного вызова не будет просто получить исключения, давайте начнем другое приложение, и вы увидите, что получает информационные отчеты:

6> application:start(inets). 
example_logger:handle_event({info_report,<0.45.0>, 
           {<0.47.0>,progress, 
           [{supervisor,{local,inets_sup}}, 
            {started, 
             [{pid,<0.48.0>}, 
             {name,ftp_sup}, 
             {mfargs,{ftp_sup,start_link,[]}}, 
             {restart_type,permanent}, 
             {shutdown,infinity}, 
             {child_type,supervisor}]}]}}, state) 
example_logger:handle_event({info_report,<0.45.0>, 
          {<0.50.0>,progress, 
           [{supervisor,{local,httpc_profile_sup}}, 
           {started, 
           [{pid,<0.51.0>}, 
           {name,httpc_manager}, 
           {mfargs, 
            {httpc_manager,start_link, 
            [default,only_session_cookies,inets]}}, 
           {restart_type,permanent}, 
           {shutdown,4000}, 
           {child_type,worker}]}]}}, state) 
example_logger:handle_event({info_report,<0.45.0>, 
          {<0.49.0>,progress, 
           [{supervisor,{local,httpc_sup}}, 
           {started, 
           [{pid,<0.50.0>}, 
           {name,httpc_profile_sup}, 
           {mfargs, 
            {httpc_profile_sup,start_link, 
            [[{httpc, 
             {default,only_session_cookies}}]]}}, 
           {restart_type,permanent}, 
           {shutdown,infinity}, 
           {child_type,supervisor}]}]}}, state) 
example_logger:handle_event({info_report,<0.45.0>, 
          {<0.49.0>,progress, 
           [{supervisor,{local,httpc_sup}}, 
           {started, 
           [{pid,<0.52.0>}, 
           {name,httpc_handler_sup}, 
           {mfargs,{httpc_handler_sup,start_link,[]}}, 
           {restart_type,permanent}, 
           {shutdown,infinity}, 
           {child_type,supervisor}]}]}}, state) 
example_logger:handle_event({info_report,<0.45.0>, 
          {<0.47.0>,progress, 
           [{supervisor,{local,inets_sup}}, 
           {started, 
           [{pid,<0.49.0>}, 
           {name,httpc_sup}, 
           {mfargs, 
            {httpc_sup,start_link, 
            [[{httpc, 
             {default,only_session_cookies}}]]}}, 
           {restart_type,permanent}, 
           {shutdown,infinity}, 
           {child_type,supervisor}]}]}}, state) 
example_logger:handle_event({info_report,<0.45.0>, 
           {<0.47.0>,progress, 
           [{supervisor,{local,inets_sup}}, 
            {started, 
             [{pid,<0.53.0>}, 
             {name,httpd_sup}, 
             {mfargs,{httpd_sup,start_link,[[]]}}, 
             {restart_type,permanent}, 
             {shutdown,infinity}, 
             {child_type,supervisor}]}]}}, state) 
example_logger:handle_event({info_report,<0.45.0>, 
           {<0.47.0>,progress, 
           [{supervisor,{local,inets_sup}}, 
            {started, 
             [{pid,<0.54.0>}, 
             {name,tftp_sup}, 
             {mfargs,{tftp_sup,start_link,[[]]}}, 
             {restart_type,permanent}, 
             {shutdown,infinity}, 
             {child_type,supervisor}]}]}}, state) 
example_logger:handle_event({info_report,<0.25.0>, 
           {<0.7.0>,progress, 
           [{application,inets}, 
            {started_at,[email protected]}]}}, state) 

Вы можете игнорировать их, если вам нравится, конечно, но вы, вероятно, следует быть осторожным, чтобы сделать уверенный, что с ним справляется какой-то журнал.

Вы можете удалить обработчик, и без обработчика TTY, то не будет никакого очевидного вывода:

7> error_logger:delete_report_handler(example_logger). 
{ok,state} 
8> 
8> spawn(fun() -> 1/0 end). 
<0.38.0> 

не означает, что нет обработчики, конечно, это означает, что нет ни одного написания этих событий к стандартному выходу/tty.