Erlang(牛仔)运行时错误处理

时间:2015-12-13 11:11:26

标签: exception erlang rebar

我正在寻找erlang中错误处理的解决方案。

主要挑战是在任何错误上下文中运行代码片段。

例如(如果可能的话)覆盖SASL记录器(或任何类似的行为),这将允许我在系统的任何一点引发异常时执行代码。

欢呼声

1 个答案:

答案 0 :(得分:2)

您可以编写自己的回调模块error_logger可以用来执行日志记录。这只是sasl所做的(它有几个记录器实现,sasl_report_tty_hsasl_report_file_hlog_mf_hd,请参阅sasl (application))。

要编写自己的实现,它并不太难,您只需要实现一个支持必要事件的gen_event回调模块。您可以查看sasl明显提供的实现,或者lager或任何其他日志记录应用程序提供的实现,但这是一个简单的实现:

-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} .

这只是标准输出的无差别转储,当然,您应该查看error_logger modulegen_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],[]}]}

现在,添加回调模块,您可以看到它也接收到异常,以及tty处理程序:

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,nonode@nohost}]}}, state)

如果您愿意,可以忽略这些,但您可能应该小心确保SOME记录器确实处理它们!

你可以删除你的处理程序,如果没有tty处理程序,就没有明显的输出:

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

并不意味着当然没有处理程序,这意味着没有人将这些事件写入标准输出/ tty。