monitoring remote error logging
Vance Shipley
vances@REDACTED
Sun Apr 25 01:55:42 CEST 2004
Continuing with my effort to use distribution for user interaction
with running applications I have written a handler for error_logger
which will forward specific reports to the user's local error_logger.
The application is running on another node as an embedded system.
The error_logger sends it's reports to standard_io which shows up
in run_erl's log files. For OA&M users start their own node and
use rpc and distribution to interact with the running application.
To monitor the reports being sent to the error_logger on the
embedded node we install a new handler in the embedded node's
error_logger. The selected events are forwarded to the user's
own error_logger. The attached user_default.erl demonstrates SASL
report monitoring. It finds all nodes running SASL and installs
the forward_error_logger.erl handler in each node's error_logger.
-Vance
Vance Shipley
Motivity Telecom Inc.
+1 519 240 3684
vances@REDACTED
-------------- next part --------------
-module(user_default).
-export([help/0, log/1]).
help() ->
shell_default:help(),
io:fwrite("** commands from user_default **~n"),
io:fwrite("log(sasl) -- start logging SASL events from all nodes~n"),
io:fwrite("log(List) -- start logging List events from all nodes~n"),
true.
log(sasl) ->
log([supervisor_report, crash_report, progress]);
log(Events) when is_list(Events) ->
%% if we're receiving sasl events we need the sasl report
%% handler installed in the local error_logger
SaslEvents = [supervisor_report, crash_report, progress],
case SaslEvents -- Events of
SaslEvents ->
App = none;
_ ->
App = sasl,
case lists:member(sasl_report_tty_h,
gen_event:which_handlers(error_logger)) of
true -> ok;
false -> application:start(sasl)
end
end,
log(log_nodes(App), Events).
log([], Events) -> ok;
log([Node|T], Events) ->
%% install the forwarding handler at each remote node
gen_event:add_handler({error_logger, Node}, forward_error_logger,
[Events, whereis(error_logger)]),
log(T, Events).
%%% internal functions
log_nodes(none) ->
nodes();
log_nodes(App) ->
Pred = fun(N) ->
lists:keymember(App, 1,
rpc:call(N, application, which_applications, []))
end,
lists:filter(Pred, nodes()).
-------------- next part --------------
-module(forward_error_logger).
-author('vances@REDACTED').
%%%
%%% An event handler for the error_logger which forwards specified
%%% report types to a remote error_logger process.
%%%
%%% e.g. all error_report and info_report messages generated on
%%% server@REDACTED sent to the error_logger process running on user@REDACTED:
%%%
%%% (user@REDACTED)1> gen_event:add_handler({error_logger, 'server@REDACTED'},
%%% forward_error_logger, [[error_report, info_report], whereis(error_logger)]).
%%%
-export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2]).
%% init(Args) -> {ok, State}
%% Args = [Types, ErrorLogger]
%% ErrorLogger = pid() of the remote error_logger
%% Types = [Type]
%% Type = EventType | ReportType
%% EventType = error_report | info_report | error| info_msg | info | emulator
%% ReportType = std_error | std_info | SASLType | OtherType
%% SASLType = supervisor_report | crash_report | progress
%% OtherType = term() Type in error_logger:error_report/2 & info_report/2
%%
init([Types, ErrorLogger]) when is_list(Types), is_pid(ErrorLogger) ->
Node = node(ErrorLogger),
monitor_node(Node, true),
{ok, {Types, Node, ErrorLogger}}.
%% handler for error_report & info_report events
handle_event({EventType, GroupLeader, {Epid, ReportType, Report}}, {Types, Node, Pid})
when node(GroupLeader) == node(),
(error_report == EventType) or (info_report == EventType) ->
case lists:member(EventType, Types) or lists:member(ReportType, Types) of
true -> gen_event:notify(Pid, {EventType, Pid, {Epid, ReportType, Report}});
false -> ok
end,
{ok, {Types, Node, Pid}};
%% handler for error, info_msg & info events
handle_event({EventType, GroupLeader, {Epid, Format, Args}}, {Types, Node, Pid})
when node(GroupLeader) == node(),
(error == EventType) or (info_msg == EventType) or (info == EventType) ->
case lists:member(EventType, Types) of
true -> gen_event:notify(Pid, {EventType, Pid, {Epid, Format, Args}});
false -> ok
end,
{ok, {Types, Node, Pid}};
handle_event(_, State) ->
{ok, State}.
%% handler for emulator events from the runtime system
handle_info({emulator, GroupLeader, Msg}, {Types, Node, Pid}) when node(GroupLeader) == node() ->
case lists:member(emulator, Types) of
true -> Pid ! {emulator, Pid, Msg};
false -> ok
end,
{ok, {Types, Node, Pid}};
handle_info({nodedown, Node}, {_Types, Node, _Pid}) ->
remove_handler;
handle_info(_, State) ->
{ok, State}.
handle_call(_Query, _) ->
{error, bad_query}.
terminate(_Reason, _State) ->
[].
More information about the erlang-questions
mailing list