diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | doc/guide.html | 12 | ||||
-rw-r--r-- | doc/guide.tex | 14 | ||||
-rw-r--r-- | src/ejabberd_config.erl | 2 | ||||
-rw-r--r-- | src/ejabberd_system_monitor.erl | 47 |
5 files changed, 70 insertions, 14 deletions
@@ -1,3 +1,12 @@ +2009-02-13 Badlop <badlop@process-one.net> + + * src/ejabberd_system_monitor.erl: Allow parametrizable watchdog + threshold: option watchdog_large_heap or chatting with the + watchdog bot (EJAB-545) + * src/ejabberd_config.erl: Likewise + * doc/guide.tex: Likewise + * doc/guide.html: Likewise + 2009-02-13 Christophe Romain <christophe.romain@process-one.net> * src/ejabberd_auth.erl: prevent from calling diff --git a/doc/guide.html b/doc/guide.html index 645ae6d5c..55ce1dc69 100644 --- a/doc/guide.html +++ b/doc/guide.html @@ -3366,14 +3366,16 @@ There are some simple and safe examples in the article <H2 CLASS="section"><!--SEC ANCHOR --><A NAME="htoc87">7.3</A>  <A HREF="#watchdog">Watchdog Alerts</A></H2><!--SEC END --><P> <A NAME="watchdog"></A> </P><P><TT>ejabberd</TT> includes a watchdog mechanism that may be useful to developers when troubleshooting a problem related to memory usage. -If a process in the <TT>ejabberd</TT> server consumes a lot of memory, +If a process in the <TT>ejabberd</TT> server consumes more memory than the configured threshold, a message is sent to the Jabber accounts defined with the option <TT>watchdog_admins</TT> - in the <TT>ejabberd</TT> configuration file. -Note that the threshold to define what is too much memory usage -is only configurable editing the source code. -Example configuration: + in the <TT>ejabberd</TT> configuration file.</P><P>The memory consumed is measured in <TT>words</TT>: +a word on 32-bit architecture is 4 bytes, and a word on 64-bit architecture 8 bytes. +The threshold by default is 1000000 words. +This value can be configured with the option <TT>watchdog_large_heap</TT>, +or in a conversation with the watchdog alert bot.</P><P>Example configuration: </P><PRE CLASS="verbatim">{watchdog_admins, ["admin2@localhost", "admin2@example.org"]}. +{watchdog_large_heap, 30000000}. </PRE><P>To remove watchdog admins, remove them in the option. To remove all watchdog admins, set the option with an empty list: </P><PRE CLASS="verbatim">{watchdog_admins, []}. diff --git a/doc/guide.tex b/doc/guide.tex index e7ea7c13e..169dc612e 100644 --- a/doc/guide.tex +++ b/doc/guide.tex @@ -4428,15 +4428,22 @@ To exit the shell, close the window or press the keys: control+c control+c. \ejabberd{} includes a watchdog mechanism that may be useful to developers when troubleshooting a problem related to memory usage. -If a process in the \ejabberd{} server consumes a lot of memory, +If a process in the \ejabberd{} server consumes more memory than the configured threshold, a message is sent to the Jabber accounts defined with the option \term{watchdog\_admins} \ind{options!watchdog\_admins} in the \ejabberd{} configuration file. -Note that the threshold to define what is too much memory usage -is only configurable editing the source code. + +The memory consumed is measured in \term{words}: +a word on 32-bit architecture is 4 bytes, +and a word on 64-bit architecture is 8 bytes. +The threshold by default is 1000000 words. +This value can be configured with the option \term{watchdog\_large\_heap}, +or in a conversation with the watchdog alert bot. + Example configuration: \begin{verbatim} {watchdog_admins, ["admin2@localhost", "admin2@example.org"]}. +{watchdog_large_heap, 30000000}. \end{verbatim} To remove watchdog admins, remove them in the option. @@ -4445,7 +4452,6 @@ To remove all watchdog admins, set the option with an empty list: {watchdog_admins, []}. \end{verbatim} - \appendix{} \makechapter{i18ni10n}{Internationalization and Localization} diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index ecf8ec30f..dc54ee884 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -356,6 +356,8 @@ process_term(Term, State) -> add_option({domain_balancing_component_number, Domain}, N, State); {watchdog_admins, Admins} -> add_option(watchdog_admins, Admins, State); + {watchdog_large_heap, LH} -> + add_option(watchdog_large_heap, LH, State); {registration_timeout, Timeout} -> add_option(registration_timeout, Timeout, State); {loglevel, Loglevel} -> diff --git a/src/ejabberd_system_monitor.erl b/src/ejabberd_system_monitor.erl index 5fa2cc4d9..505b0994b 100644 --- a/src/ejabberd_system_monitor.erl +++ b/src/ejabberd_system_monitor.erl @@ -51,7 +51,12 @@ %% Description: Starts the server %%-------------------------------------------------------------------- start_link() -> - gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). + LH = case ejabberd_config:get_local_option(watchdog_large_heap) of + I when is_integer(I) -> I; + _ -> 1000000 +end, + Opts = [{large_heap, LH}], + gen_server:start_link({local, ?MODULE}, ?MODULE, Opts, []). process_command(From, To, Packet) -> case To of @@ -90,9 +95,10 @@ process_command(From, To, Packet) -> %% {stop, Reason} %% Description: Initiates the server %%-------------------------------------------------------------------- -init([]) -> +init(Opts) -> + LH = proplists:get_value(large_heap, Opts), process_flag(priority, high), - erlang:system_monitor(self(), [{large_heap, 1000000}]), + erlang:system_monitor(self(), [{large_heap, LH}]), lists:foreach( fun(Host) -> ejabberd_hooks:add(local_send_to_resource_hook, Host, @@ -109,10 +115,24 @@ init([]) -> %% {stop, Reason, State} %% Description: Handling call messages %%-------------------------------------------------------------------- +handle_call({get, large_heap}, _From, State) -> + {reply, get_large_heap(), State}; +handle_call({set, large_heap, NewValue}, _From, State) -> + MonSettings = erlang:system_monitor(self(), [{large_heap, NewValue}]), + OldLH = get_large_heap(MonSettings), + NewLH = get_large_heap(), + {reply, {lh_changed, OldLH, NewLH}, State}; handle_call(_Request, _From, State) -> Reply = ok, {reply, Reply, State}. +get_large_heap() -> + MonSettings = erlang:system_monitor(), + get_large_heap(MonSettings). +get_large_heap(MonSettings) -> + {_MonitorPid, Options} = MonSettings, + proplists:get_value(large_heap, Options). + %%-------------------------------------------------------------------- %% Function: handle_cast(Msg, State) -> {noreply, State} | %% {noreply, State, Timeout} | @@ -165,7 +185,7 @@ process_large_heap(Pid, Info) -> JIDs /= [] -> DetailedInfo = detailed_info(Pid), Body = io_lib:format( - "(~w) The process ~w is consuming too much memory: ~w.~n" + "(~w) The process ~w is consuming too much memory:~n~p~n" "~s", [node(), Pid, Info, DetailedInfo]), From = jlib:make_jid("", Host, "watchdog"), @@ -303,14 +323,25 @@ process_command1(From, To, Body) -> process_command2(["kill", SNode, SPid], From, To) -> Node = list_to_atom(SNode), remote_command(Node, [kill, SPid], From, To); +process_command2(["showlh", SNode], From, To) -> + Node = list_to_atom(SNode), + remote_command(Node, [showlh], From, To); +process_command2(["setlh", SNode, NewValueString], From, To) -> + Node = list_to_atom(SNode), + NewValue = list_to_integer(NewValueString), + remote_command(Node, [setlh, NewValue], From, To); process_command2(["help"], From, To) -> send_message(To, From, help()); process_command2(_, From, To) -> send_message(To, From, help()). + help() -> "Commands:\n" - " kill <node> <pid>". + " kill <node> <pid>\n" + " showlh <node>\n" + " setlh <node> <integer>". + remote_command(Node, Args, From, To) -> Message = @@ -325,6 +356,12 @@ remote_command(Node, Args, From, To) -> process_remote_command([kill, SPid]) -> exit(list_to_pid(SPid), kill), "ok"; +process_remote_command([showlh]) -> + Res = gen_server:call(ejabberd_system_monitor, {get, large_heap}), + io_lib:format("Current large heap: ~p", [Res]); +process_remote_command([setlh, NewValue]) -> + {lh_changed, OldLH, NewLH} = gen_server:call(ejabberd_system_monitor, {set, large_heap, NewValue}), + io_lib:format("Result of set large heap: ~p --> ~p", [OldLH, NewLH]); process_remote_command(_) -> throw(unknown_command). |