我正在寻找erlang中错误处理的解决方案。
主要挑战是在任何错误上下文中运行代码片段。
例如(如果可能的话)覆盖SASL记录器(或任何类似的行为),这将允许我在系统的任何一点引发异常时执行代码。
欢呼声
答案 0 :(得分:2)
您可以编写自己的回调模块error_logger
可以用来执行日志记录。这只是sasl所做的(它有几个记录器实现,sasl_report_tty_h
,sasl_report_file_h
和log_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 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],[]}]}
现在,添加回调模块,您可以看到它也接收到异常,以及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。