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