<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, []}.
\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.
{watchdog_admins, []}.
\end{verbatim}
-
\appendix{}
\makechapter{i18ni10n}{Internationalization and Localization}
%% 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
%% {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,
%% {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} |
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"),
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 =
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).