Permalink
Browse files

Add lots of EDoc stuff, minor cleanups & refactoring

  • Loading branch information...
1 parent 0dd0975 commit 637cd290c3c20d84c8c2699008364995ef86c660 @slfritchie slfritchie committed Nov 3, 2010
Showing with 100 additions and 32 deletions.
  1. +66 −0 src/riak_err_app.erl
  2. +15 −24 src/riak_err_handler.erl
  3. +12 −8 src/riak_err_monitor.erl
  4. +7 −0 src/riak_err_stdlib.erl
View
@@ -14,6 +14,72 @@
%% specific language governing permissions and limitations
%% under the License.
+%% @doc A memory-limited info/error/warning event handler.
+%%
+%% Replace the OTP default error_logger's event handler (which
+%% can cause memory use problems when handling very large messages)
+%% with a handler that will use a limited amount of RAM but is
+%% otherwise equivalent.
+%%
+%% Strictly speaking, this library need be a "code only" application,
+%% i.e. an OTP application without any support processes (like the
+%% <tt>stdlib</tt> OTP application). However, there's one significant
+%% reason why <tt>riak_err</tt> would want to have a small monitoring
+%% server running. The reason is as follows:
+%%
+%% The OTP <tt>kernel</tt> application's has a gen_event-based process
+%% with the registered name <tt>error_logger</tt> that handles all
+%% system info/error/warning messages, e.g., submitted by
+%% <tt>error_logger:info_msg()</tt> and related functions. If there
+%% is a problem with an <tt>error_logger</tt> event handler (e.g.,
+%% throws an exception), the handler is silently removed from handling
+%% further events.
+%%
+%% We wish to know about all events, good and bad, despite software
+%% bugs. Therefore, if there's an error in an event handler, we want
+%% a monitor process to find out about the error and act to re-install
+%% the handler. If we don't re-install the handler, we will
+%% <em>never</em> see another event logged. We want happy event
+%% logging, but we do not want to travel the "Ignorance is bliss" road
+%% to find that happiness.
+%%
+%% <ol>
+%%
+%% <li> We use a long-lived gen_server-based process (running code in
+%% this module) to be our monitor. </li>
+%%
+%% <li> We install the handler using
+%% <tt>gen_event:add_sup_handler/3</tt>. If the handler exits or
+%% throws an exception, we'll be sent a <tt>{gen_event_EXIT, ...}</tt>
+%% message. </li>
+%%
+%% <li> If we receive the <tt>{gen_event_EXIT, ...}</tt> bad news
+%% message, we exit. Our supervisor will restart us, and the
+%% side-effect of running our <tt>init()</tt> function is
+%% re-installing our custom event handler. </li>
+%%
+%%</ol>
+%%
+%% === Configuration ===
+%%
+%% There are two config knobs may be specified on the command line
+%% via "-riak_err KnobName Integer" on the command line or (in a
+%% Basho application like Riak) via the same "-riak_err KnobName Integer"
+%% line in the <tt>etc/vm.args</tt> file):
+%%
+%% <ol>
+%% <li> <tt>term_max_size</tt> For arguments formatted in FormatString &amp;
+%% ArgList style, if the total size of ArgList is more than term_max_size,
+%% then we'll ignore FormatString and log the message with a well-known
+%% (and therefore safe) formatting string. The default is 10KBytes. </li>
+%%
+%% <li> <tt>fmt_max_bytes</tt> When formatting a log-related term that might
+%% be "big", limit the term's formatted output to a maximum of
+%% <tt>fmt_max_bytes</tt> bytes. The default is 12KBytes. </li>
+%% </ol>
+%%
+%% For example, <tt>erl -riak_err term_max_size 8192 fmt_max_bytes 9000</tt>.
+
-module(riak_err_app).
-behaviour(application).
View
@@ -14,25 +14,13 @@
%% specific language governing permissions and limitations
%% under the License.
-%% @doc Replace the OTP default error_logger's event handler (which
+%% @doc A memory-limited info/error/warning event handler.
+%%
+%% Replace the OTP default error_logger's event handler (which
%% can cause memory use problems when handling very large messages)
%% with a handler that will use a limited amount of RAM but is
%% otherwise equivalent.
%%
-%% There are two config knobs may be specified on the command line
-%% via "-riak_err KnobName Integer" on the command line or (in a
-%% Basho application like Riak) via the same "-riak_err KnobName Integer"
-%% line in the <tt>etc/vm.args</tt> file):
-%% <ol>
-%% <li> <tt>term_max_size</tt> For arguments formatted in FormatString &amp;
-%% ArgList style, if the total size of ArgList is more than term_max_size,
-%% then we'll ignore FormatString and log the message with a well-known
-%% (and therefore safe) formatting string. The default is 10KBytes. </li>
-%% <li> <tt>fmt_max_bytes</tt> When formatting a log-related term that might
-%% be "big", limit the term's formatted output to a maximum of
-%% <tt>fmt_max_bytes</tt> bytes. The default is 12KBytes. </li>
-%% </ol>
-
%% TODO:
%%
%% * The default Riak* stuff uses the
@@ -41,16 +29,13 @@
%% That means that I need to reimplement level filtering and formatting
%% and scribbling to a file??
%% * Find TODO labels and fix them
-%% * Double-check license compat:
-%% * trunc_io:
-%% * EPL stuff at bottom
-module(riak_err_handler).
-behaviour(gen_event).
%% External exports
--export([start_link/0, add_handler/0,
+-export([add_sup_handler/0,
set_term_max_size/1, set_fmt_max_bytes/1,
get_state/0]).
@@ -59,26 +44,32 @@
code_change/3]).
-record(state, {
- %% .
term_max_size = 10000,
fmt_max_bytes = 8000
}).
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
-start_link() ->
- gen_event:start_link({local, ?MODULE}).
-add_handler() ->
- gen_event:add_handler(?MODULE, ?MODULE, []).
+%% @doc Add a supervised handler to the OTP kernel's
+%% <tt>error_logger</tt> event server.
+
+add_sup_handler() ->
+ gen_event:add_sup_handler(error_logger, ?MODULE, []).
+
+%% @doc Change the internal value of <tt>set_term_max_size</tt>.
set_term_max_size(Num) ->
gen_event:call(error_logger, ?MODULE, {set_term_max_size, Num}, infinity).
+%% @doc Change the internal value of <tt>set_fmt_max_bytes</tt>.
+
set_fmt_max_bytes(Num) ->
gen_event:call(error_logger, ?MODULE, {set_fmt_max_bytes, Num}, infinity).
+%% @doc Debugging: get internal state record.
+
get_state() ->
gen_event:call(error_logger, ?MODULE, {get_state}, infinity).
View
@@ -14,6 +14,8 @@
%% specific language governing permissions and limitations
%% under the License.
+%% @doc Small server to monitor the riak_err custom SASL event handler.
+
-module(riak_err_monitor).
-behaviour(gen_server).
@@ -55,7 +57,7 @@ stop() ->
%%----------------------------------------------------------------------
init([]) ->
%% Add our custom handler.
- ok = gen_event:add_sup_handler(error_logger, riak_err_handler, []),
+ ok = riak_err_handler:add_sup_handler(),
%% Disable the default error logger handlers and SASL handlers.
[gen_event:delete_handler(error_logger, Handler, {stop_please, ?MODULE}) ||
@@ -83,7 +85,8 @@ handle_call(_Request, _From, State) ->
%%----------------------------------------------------------------------
handle_cast(Msg, State) ->
{Str, _} = trunc_io:print(Msg, State#state.max_len),
- io:format("~w: ~s:handle_cast got ~s\n", [self(), ?MODULE, Str]),
+ error_logger:error_msg("~w: ~s:handle_cast got ~s\n",
+ [self(), ?MODULE, Str]),
{noreply, State}.
%%----------------------------------------------------------------------
@@ -94,19 +97,20 @@ handle_cast(Msg, State) ->
%%----------------------------------------------------------------------
handle_info({gen_event_EXIT, Handler, Reason}, State) ->
%% Our handler ought to be bullet-proof ... but it wasn't, bummer.
+ %% Double bummer, we cannot use the handler to log this event.
+ %%
%% We will stop now, and our supervisor will restart us and thus
- %% reinstate the custom event handler.
+ %% reinstate the custom event handler. If all goes well, we will
+ %% be restarted after only a few milliseconds.
+
{Str, _} = trunc_io:print(Reason, State#state.max_len),
io:format("~w: ~s: handler ~w exited for reason ~s\n",
[self(), ?MODULE, Handler, Str]),
{stop, gen_event_EXIT, State};
-handle_info(foo, _State) ->
- bar;
-handle_info(bar, _State) ->
- throw(blarf);
handle_info(Info, State) ->
{Str, _} = trunc_io:print(Info, State#state.max_len),
- io:format("~w: ~s:handle_info got ~s\n", [self(), ?MODULE, Str]),
+ error_logger:error_msg("~w: ~s:handle_info got ~s\n",
+ [self(), ?MODULE, Str]),
{noreply, State}.
%%----------------------------------------------------------------------
View
@@ -17,6 +17,13 @@
%% %CopyrightEnd%
%%
+%% @doc Functions from Erlang OTP distribution that are really useful
+%% but aren't exported.
+%%
+%% All functions in this module are covered by the Erlang/OTP source
+%% distribution's license, the Erlang Public License. See
+%% http://www.erlang.org/ for full details.
+
-module(riak_err_stdlib).
-export([write_time/2, maybe_utc/1]).
-export([is_my_error_report/1, is_my_info_report/1]).

0 comments on commit 637cd29

Please sign in to comment.