aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/common_test/doc/src/ct_hooks_chapter.xml9
-rw-r--r--lib/kernel/doc/src/error_logger.xml48
-rw-r--r--lib/kernel/doc/src/introduction_chapter.xml1
-rw-r--r--lib/kernel/doc/src/kernel_app.xml11
-rw-r--r--lib/kernel/doc/src/logger.xml184
-rw-r--r--lib/kernel/doc/src/logger_chapter.xml222
-rw-r--r--lib/kernel/doc/src/logger_disk_log_h.xml22
-rw-r--r--lib/kernel/doc/src/logger_formatter.xml40
-rw-r--r--lib/kernel/doc/src/logger_std_h.xml19
-rw-r--r--lib/runtime_tools/doc/src/LTTng.xml2
-rw-r--r--lib/sasl/doc/src/error_logging.xml52
-rw-r--r--lib/sasl/doc/src/sasl_app.xml9
-rw-r--r--lib/stdlib/doc/src/gen_event.xml3
-rw-r--r--lib/stdlib/doc/src/gen_server.xml6
-rw-r--r--lib/stdlib/doc/src/gen_statem.xml4
-rw-r--r--lib/stdlib/doc/src/proc_lib.xml50
-rw-r--r--system/doc/reference_manual/introduction.xml2
-rw-r--r--system/doc/system_principles/error_logging.xml113
-rw-r--r--system/doc/system_principles/system_principles.xml2
19 files changed, 469 insertions, 330 deletions
diff --git a/lib/common_test/doc/src/ct_hooks_chapter.xml b/lib/common_test/doc/src/ct_hooks_chapter.xml
index 7ecc2e4298..3957c0f4a5 100644
--- a/lib/common_test/doc/src/ct_hooks_chapter.xml
+++ b/lib/common_test/doc/src/ct_hooks_chapter.xml
@@ -501,12 +501,13 @@
<tag><c>cth_log_redirect</c></tag>
<item>
<p>Built-in</p>
- <p>Captures all <c>error_logger</c> and SASL logging
- events and prints them to the current test case log. If an event cannot be
- associated with a test case, it is printed in the <c>Common Test</c> framework log.
+ <p>Captures all log events that would normally be printed by the default
+ logger handler, and prints them to the current test case log.
+ If an event cannot be associated with a test case, it is printed in
+ the <c>Common Test</c> framework log.
This happens for test cases running in parallel and events occuring
in-between test cases. You can configure the level of
- <seealso marker="sasl:sasl_app">SASL</seealso> events report
+ <seealso marker="sasl:sasl_app">SASL</seealso> reports
using the normal SASL mechanisms.</p>
</item>
<tag><c>cth_surefire</c></tag>
diff --git a/lib/kernel/doc/src/error_logger.xml b/lib/kernel/doc/src/error_logger.xml
index c9fe9484e4..e91fc734a4 100644
--- a/lib/kernel/doc/src/error_logger.xml
+++ b/lib/kernel/doc/src/error_logger.xml
@@ -36,41 +36,31 @@
<p>In OTP-21, a new API for logging was added to Erlang/OTP. The
old <c>error_logger</c> module can still be used by legacy
code, but new code should use the new API instead.</p>
+ <p><c>error_logger</c> is no longer started by default, but is
+ automatically started when an event handler is added
+ with <c>error_logger:add_report_handler/1,2</c>. The <c>error_logger</c>
+ module is then also added as a handler to the new logger.</p>
<p>See <seealso marker="logger"><c>logger(3)</c></seealso> and
the <seealso marker="logger_chapter">Logging</seealso> chapter
- in the user's guide for more information.</p>
+ in the User's Guide for more information.</p>
</note>
<p>The Erlang <em>error logger</em> is an event manager (see
<seealso marker="doc/design_principles:des_princ">OTP Design Principles</seealso> and
<seealso marker="stdlib:gen_event"><c>gen_event(3)</c></seealso>),
- registered as <c>error_logger</c>. Errors, warnings, and info events
- are sent to the error logger from the Erlang runtime system and
- the different Erlang/OTP applications. The events are, by default,
- logged to the terminal. Notice that an event from a process <c>P</c> is
- logged at the node of the group leader of <c>P</c>. This means
- that log output is directed to the node from which a process was
- created, which not necessarily is the same node as where it is
- executing.</p>
- <p>Initially, <c>error_logger</c> has only a primitive event
- handler, which buffers and prints the raw event messages. During
- system startup, the Kernel application replaces this with a
- <em>standard event handler</em>, by default one that writes
- nicely formatted output to the terminal. Kernel can also be
- configured so that events are logged to a file instead, or not logged at all,
- see <seealso marker="kernel_app"><c>kernel(6)</c></seealso>.</p>
- <p>Also the SASL application, if started, adds its own event
- handler, which by default writes supervisor, crash, and progress
- reports to the terminal. See
- <seealso marker="sasl:sasl_app"><c>sasl(6)</c></seealso>.</p>
- <p>It is recommended that user-defined applications report
- errors through the error logger to get uniform reports.
- User-defined event handlers can be added to handle application-specific
- events, see
- <seealso marker="#add_report_handler/1"><c>add_report_handler/1,2</c></seealso>.
- Also, a useful event handler is provided in STDLIB for multi-file
- logging of events, see
- <seealso marker="stdlib:log_mf_h"><c>log_mf_h(3)</c></seealso>.</p>
+ registered as <c>error_logger</c>.</p>
+ <p>Error logger is no longer started by default, but is
+ automatically started when an event handler is added
+ with <seealso marker="#add_report_handler/1">
+ <c>add_report_handler/1,2</c></seealso>. The <c>error_logger</c>
+ module is then also added as a handler to the new logger,
+ causing log events to be forwarded from logger to error logger,
+ and consequently to all installed error logger event
+ handlers.</p>
+ <p>User-defined event handlers can be added to handle application-specific
+ events.</p>
+ <p>Existing event handlers provided by STDLIB and SASL are still
+ available, but are no longer used by OTP.</p>
<p>Warning events were introduced in Erlang/OTP R9C and are enabled
by default as from Erlang/OTP 18.0. To retain backwards compatibility
with existing user-defined event handlers, the warning events can be
@@ -191,7 +181,7 @@ ok</pre>
<p>The <c>error_logger_format_depth</c> variable
is <seealso marker="kernel_app#deprecated-configuration-parameters">
deprecated</seealso> since
- the <seealso marker="logger">Logger API</seealso> was
+ the <seealso marker="logger">logging API</seealso> was
introduced in OTP-21. The variable, and this function, are
kept for backwards compatibility since they still might be
used by legacy report handlers.</p>
diff --git a/lib/kernel/doc/src/introduction_chapter.xml b/lib/kernel/doc/src/introduction_chapter.xml
index 6e6990ddda..2eadc70abf 100644
--- a/lib/kernel/doc/src/introduction_chapter.xml
+++ b/lib/kernel/doc/src/introduction_chapter.xml
@@ -46,7 +46,6 @@
<item>Start, stop, supervision, configuration, and distribution of applications</item>
<item>Code loading</item>
<item>Logging</item>
- <item>Error logging</item>
<item>Global name service</item>
<item>Supervision of Erlang/OTP</item>
<item>Communication with sockets</item>
diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml
index 7cd05dab14..5bc423afb6 100644
--- a/lib/kernel/doc/src/kernel_app.xml
+++ b/lib/kernel/doc/src/kernel_app.xml
@@ -42,7 +42,6 @@
<item>Start, stop, supervision, configuration, and distribution of applications</item>
<item>Code loading</item>
<item>Logging</item>
- <item>Error logging</item>
<item>Global name service</item>
<item>Supervision of Erlang/OTP</item>
<item>Communication with sockets</item>
@@ -194,9 +193,9 @@
If the SASL application is started,
these log events will be sent to a second handler instance
named <c>sasl_h</c>, according to values of the SASL
- environment variables <c>sasl_error_logger</c>
+ configuration parameter <c>sasl_error_logger</c>
and <c>sasl_errlog_type</c>, see
- <seealso marker="sasl:sasl_app#configuration">SASL(6)
+ <seealso marker="sasl:sasl_app#deprecated_error_logger_config">sasl(6)
</seealso></p>
<p>The default value is <c>false</c>.</p>
<p>See chapter <seealso marker="logger_chapter#compatibility">Backwards
@@ -271,7 +270,7 @@
<tag><c>inet_parse_error_log = silent</c></tag>
<item>
<p>If set, no
- <c>error_logger</c> messages are generated when erroneous
+ <c>logger</c> messages are generated when erroneous
lines are found and skipped in the various Inet configuration
files.</p>
</item>
@@ -486,7 +485,7 @@ MaxT = TickTime + TickTime / 4</code>
old <c>error_logger</c> event manager, and event handlers
running on this manager, will still work, but they are not used
by default.</p>
- <p>The following application environment variables can still be
+ <p>The following application configuration parameters can still be
set, but they will only be used if the corresponding new logger
variables are not set.</p>
<taglist>
@@ -519,12 +518,12 @@ erl -kernel logger '[{handler,default,logger_std_h,#{formatter=>{logger_formatte
<seealso marker="disk_log"><c>disk_log(3)</c></seealso>,
<seealso marker="erl_boot_server"><c>erl_boot_server(3)</c></seealso>,
<seealso marker="erl_ddll"><c>erl_ddll(3)</c></seealso>,
- <seealso marker="error_logger"><c>error_logger(3)</c></seealso>,
<seealso marker="file"><c>file(3)</c></seealso>,
<seealso marker="global"><c>global(3)</c></seealso>,
<seealso marker="global_group"><c>global_group(3)</c></seealso>,
<seealso marker="heart"><c>heart(3)</c></seealso>,
<seealso marker="inet"><c>inet(3)</c></seealso>,
+ <seealso marker="logger"><c>logger(3)</c></seealso>,
<seealso marker="net_kernel"><c>net_kernel(3)</c></seealso>,
<seealso marker="os"><c>os(3)</c></seealso>,
<seealso marker="pg2"><c>pg2(3)</c></seealso>,
diff --git a/lib/kernel/doc/src/logger.xml b/lib/kernel/doc/src/logger.xml
index cac9c39f2a..f7e740e90d 100644
--- a/lib/kernel/doc/src/logger.xml
+++ b/lib/kernel/doc/src/logger.xml
@@ -33,23 +33,51 @@
<file>logger.xml</file>
</header>
<module>logger</module>
- <modulesummary>API module for the logger.</modulesummary>
+ <modulesummary>API module for logging in Erlang/OTP.</modulesummary>
<description>
+
+<!-- From old error_logger ref man:
+ Errors, warnings, and info events
+ are sent to the error logger from the Erlang runtime system and
+ the different Erlang/OTP applications. The events are, by default,
+ logged to the terminal. Notice that an event from a process <c>P</c> is
+ logged at the node of the group leader of <c>P</c>. This means
+ that log output is directed to the node from which a process was
+ created, which not necessarily is the same node as where it is
+ executing.</p>
+ <p>Initially, <c>error_logger</c> has only a primitive event
+ handler, which buffers and prints the raw event messages. During
+ system startup, the Kernel application replaces this with a
+ <em>standard event handler</em>, by default one that writes
+ nicely formatted output to the terminal. Kernel can also be
+ configured so that events are logged to a file instead, or not logged at all,
+ see <seealso marker="kernel_app"><c>kernel(6)</c></seealso>.</p>
+ <p>Also the SASL application, if started, adds its own event
+ handler, which by default writes supervisor, crash, and progress
+ reports to the terminal. See
+ <seealso marker="sasl:sasl_app"><c>sasl(6)</c></seealso>.</p>
+ <p>It is recommended that user-defined applications report
+ errors through the error logger to get uniform reports.
+-->
+
+
+
<p>
- This module is the main logger API. It contains functions that allow
- application to use a single log API and the system to manage those log
- events independently. To log events the logger
- <seealso marker="#macros">macros</seealso> should be used. For instance,
- to log a new error log event:</p>
+ This module is the main API for logging in Erlang/OTP. It
+ contains functions that allow applications to use a single log
+ API and the system to manage those log events independently. Use
+ the <seealso marker="#emergency-1">API functions</seealso> or the log
+ <seealso marker="#macros">macros</seealso> to log events. For instance,
+ to log a new error event:</p>
<code>
?LOG_ERROR("error happened because: ~p",[Reason]). %% With macro
logger:error("error happened because: ~p",[Reason]). %% Without macro
</code>
- <p>This log event will then be sent to the configured log handlers which
- by default means that it will be printed to the console. If you want
+ <p>This log event is then sent to the configured log handlers which
+ by default means that it is be printed to the console. If you want
your systems logs to be printed to a file instead of the console you
- have to configure the default handler to do so. The simplest way is
+ must configure the default handler to do so. The simplest way is
to include the following in your <seealso marker="config"><c>sys.config</c></seealso>.</p>
<code>
[{kernel,
@@ -63,7 +91,7 @@ logger:error("error happened because: ~p",[Reason]). %% Without macro
<list type="bulleted">
<item>how to use the API,
see <seealso marker="logger_chapter">the User's Guide</seealso>.</item>
- <item>how to configure logger,
+ <item>how to configure Logger,
see the <seealso marker="logger_chapter#configuration">Configuration</seealso>
section in the User's Guide.</item>
<item>the convinience macros in logger.hrl,
@@ -129,8 +157,8 @@ logger:error("error happened because: ~p",[Reason]). %% Without macro
<c>update_process_metadata/1</c></seealso>.</p>
<p>Logger merges all the metadata maps before forwarding the
log event to the handlers. If the same keys occur, values
- from the log call overwrites process metadata, which in turn
- overwrites values set by Logger.</p>
+ from the log call overwrite process metadata, which in turn
+ overwrite values set by Logger.</p>
</desc>
</datatype>
<datatype>
@@ -165,7 +193,8 @@ logger:error("error happened because: ~p",[Reason]). %% Without macro
<datatype>
<name name="filter"/>
<desc>
- <p>A filter which can be installed for logger or for a handler.</p>
+ <p>A filter which can be installed for the logger part of
+ Logger, or for a handler.</p>
</desc>
</datatype>
<datatype>
@@ -213,9 +242,9 @@ logger:error("error happened because: ~p",[Reason]). %% Without macro
<item><c>?LOG_DEBUG(FunOrFormat,Args[,Metadata])</c></item>
</list>
- <p>All macros expand to a call to logger, where <c>Level</c> is
- taken from the macro name, and location data is added. See the
- description of
+ <p>All macros expand to a call to Logger, where <c>Level</c> is
+ taken from the macro name, and location data is added to the
+ metadata. See the description of
the <seealso marker="#type-metadata"><c>metadata()</c></seealso>
type for more information about the location data.</p>
@@ -335,23 +364,26 @@ logger:error("error happened because: ~p",[Reason]). %% Without macro
<func>
<name name="get_logger_config" arity="0"/>
- <fsummary>Lookup the current configuration for logger.</fsummary>
+ <fsummary>Look up the current configuration for the logger part
+ of Logger.</fsummary>
<desc>
- <p>Lookup the current configuration for logger.</p>
+ <p>Look up the current configuration for the logger part of
+ Logger.</p>
</desc>
</func>
<func>
<name name="get_handler_config" arity="1"/>
- <fsummary>Lookup the current configuration for the given handler.</fsummary>
+ <fsummary>Look up the current configuration for the given
+ handler.</fsummary>
<desc>
- <p>Lookup the current configuration for the given handler.</p>
+ <p>Look up the current configuration for the given handler.</p>
</desc>
</func>
<func>
<name name="i" arity="0"/>
- <fsummary>Get all logger configurations</fsummary>
+ <fsummary>Get all Logger configurations</fsummary>
<desc>
<p>Same as <seealso marker="#i/1"><c>logger:i(term)</c></seealso></p>
</desc>
@@ -361,28 +393,28 @@ logger:error("error happened because: ~p",[Reason]). %% Without macro
<name name="i" arity="1" clause_i="1"/>
<name name="i" arity="1" clause_i="2"/>
<name name="i" arity="1" clause_i="3"/>
- <fsummary>Get all logger configurations</fsummary>
+ <fsummary>Get all Logger configurations</fsummary>
<desc>
- <p>Display or return all current logger configuration.</p>
+ <p>Display or return all current Logger configurations.</p>
<taglist>
<tag><c><anno>Action</anno> = string</c></tag>
<item>
- <p>Return the pretty printed current logger configuration
+ <p>Return the pretty printed current Logger configuration
as iodata.</p>
</item>
<tag><c><anno>Action</anno> = term</c></tag>
<item>
- <p>Return the current logger configuration as a term. The
- format of this term may change inbetween releases. For a
+ <p>Return the current Logger configuration as a term. The
+ format of this term may change between releases. For a
stable format use <seealso marker="#get_handler_config/1">
<c>logger:get_handler_config/1</c></seealso>
and <seealso marker="#get_logger_config/0">
- <c>logger:get_logger_config/0</c></seealso>.
- The same as calling <c>logger:i()</c>.</p>
+ <c>logger:get_logger_config/0</c></seealso>.</p>
+ <p>The same as calling <c>logger:i()</c>.</p>
</item>
<tag><c><anno>Action</anno> = print</c></tag>
<item>
- <p>Pretty print all the current logger configuration to
+ <p>Pretty print all the current Logger configuration to
standard out. Example:</p>
<code><![CDATA[1> logger:i(print).
Current logger configuration:
@@ -423,9 +455,9 @@ Current logger configuration:
<func>
<name name="add_logger_filter" arity="2"/>
- <fsummary>Add a filter to the logger.</fsummary>
+ <fsummary>Add a filter to the logger part of Logger.</fsummary>
<desc>
- <p>Add a filter to the logger.</p>
+ <p>Add a filter to the logger part of Logger.</p>
<p>The filter fun is called with the log event as the first
parameter, and the specified <c>filter_args()</c> as the
second parameter.</p>
@@ -436,8 +468,8 @@ Current logger configuration:
<item>
<p>The filter <em>passed</em>. The next logger filter, if
any, is applied. If no more logger filters exist, the
- log event is forwarded to the handler part of the
- logger, where handler filters are applied.</p>
+ log event is forwarded to the handler part of Logger,
+ where handler filters are applied.</p>
</item>
<tag><c>stop</c></tag>
<item>
@@ -449,9 +481,9 @@ Current logger configuration:
<p>The filter has no knowledge of the log event. The next
logger filter, if any, is applied. If no more logger
filters exist, the value of the <c>filter_default</c>
- configuration parameter for the logger specifies if the
- log event shall be discarded or forwarded to the handler
- part.</p>
+ configuration parameter for the logger part specifies if
+ the log event shall be discarded or forwarded to the
+ handler part.</p>
</item>
</taglist>
<p>See section <seealso marker="logger_chapter#Filter">
@@ -505,10 +537,10 @@ Current logger configuration:
<func>
<name name="remove_logger_filter" arity="1"/>
- <fsummary>Remove a filter from the logger.</fsummary>
+ <fsummary>Remove a filter from the logger part of Logger.</fsummary>
<desc>
<p>Remove the filter identified
- by <c><anno>FilterId</anno></c> from the logger.</p>
+ by <c><anno>FilterId</anno></c> from the logger part of Logger.</p>
</desc>
</func>
@@ -548,21 +580,21 @@ Current logger configuration:
<p>Set the log level for the
specified <c><anno>Module</anno></c>.</p>
<p>The log level for a module overrides the global log level
- of the logger for log event originating from the module in
+ of Logger for log events originating from the module in
question. Notice, however, that it does not override the
level configuration for any handler.</p>
- <p>For example: Assume that the global log level for the
- logger is <c>info</c>, and there is one handler, <c>h1</c>,
- with level <c>info</c> and one handler, <c>h2</c>, with
+ <p>For example: Assume that the global log level for Logger
+ is <c>info</c>, and there is one handler, <c>h1</c>, with
+ level <c>info</c> and one handler, <c>h2</c>, with
level <c>debug</c>.</p>
<p>With this configuration, no debug messages will be logged,
since they are all stopped by the global log level.</p>
- <p>If the level for <c>mymodule</c> is set now set
+ <p>If the level for <c>mymodule</c> is now set
to <c>debug</c>, then debug events from this module will be
logged by the handler <c>h2</c>, but not by
handler <c>h1</c>.</p>
<p>Debug events from other modules are still not logged.</p>
- <p>To change the global log level for the logger, use
+ <p>To change the global log level for Logger, use
<seealso marker="#set_logger_config/2">
<c>logger:set_logger_config(level,Level)</c></seealso>.</p>
<p>To change the log level for a handler, use
@@ -572,9 +604,10 @@ Current logger configuration:
<p>The originating module for a log event is only detected
if <c>mfa=>{Module,Function,Arity}</c> exists in the
metadata. When log macros are used, this association is
- automatically added to all log events. If the logger API
+ automatically added to all log events. If an API function
is called directly, without using a macro, the logging
- client must explicitly add this information.</p>
+ client must explicitly add this information if module
+ levels shall have any effect.</p>
</note>
</desc>
</func>
@@ -590,10 +623,11 @@ Current logger configuration:
<func>
<name name="add_handlers" arity="1" clause_i="1"/>
- <fsummary>Setup logger handlers from the applications configuration parameters.</fsummary>
+ <fsummary>Set up log handlers from the application's
+ configuration parameters.</fsummary>
<desc>
<p>Reads the application configuration parameter <c>logger</c> and
- calls <c>logger:add_handlers/1</c> with it contents.</p>
+ calls <c>logger:add_handlers/1</c> with its contents.</p>
</desc>
</func>
@@ -602,11 +636,12 @@ Current logger configuration:
<fsummary>Setup logger handlers.</fsummary>
<type name="config_handler"/>
<desc>
- <p>This function should be used by custom logger handlers to make
+ <p>This function should be used by custom Logger handlers to make
configuration consistent no matter which handler the system uses.
- Normal usage to to add a call to <c>logger:add_handlers/1</c>
- just after the processes that the handler needs are started
- and pass the applications logger config as an argument. Eg.</p>
+ Normal usage is to add a call to <c>logger:add_handlers/1</c>
+ just after the processes that the handler needs are started,
+ and pass the application's <c>logger</c> configuration as the argument.
+ For example:</p>
<code>
-behaviour(application).
start(_, []) ->
@@ -616,19 +651,20 @@ start(_, []) ->
{ok, Pid, []};
Error -> Error
end.</code>
- <p>This will read the <c>logger</c> configuration parameter from
- the handler application and start the configured handlers. The contents
- of the configuration use the same rules as the
+ <p>This reads the <c>logger</c> configuration parameter from
+ the <c>my_all</c> application and starts the configured
+ handlers. The contents of the configuration use the same
+ rules as the
<seealso marker="logger_chapter#handler-configuration">logger handler configuration</seealso>.
</p>
- <p>If the handler is meant to replace the default handler the kernels
- default handlers have to be disabled before the new handler is added.
- A <c>sys.config</c> file that disables the kernel handler and adds
- a custom handler could looks like this:</p>
+ <p>If the handler is meant to replace the default handler, the Kernel's
+ default handler have to be disabled before the new handler is added.
+ A <c>sys.config</c> file that disables the Kernel handler and adds
+ a custom handler could look like this:</p>
<code>
[{kernel,
[{logger,
- %% Disable the default kernel handler
+ %% Disable the default Kernel handler
[{handler,default,undefined}]}]},
{my_app,
[{logger,
@@ -640,10 +676,10 @@ start(_, []) ->
<func>
<name name="set_logger_config" arity="1"/>
- <fsummary>Set configuration data for the logger.</fsummary>
+ <fsummary>Set configuration data for the logger part of Logger.</fsummary>
<desc>
- <p>Set configuration data for the logger. This overwrites the
- current logger configuration.</p>
+ <p>Set configuration data for the logger part of Logger. This
+ overwrites the current logger configuration.</p>
<p>To modify the existing configuration,
use <seealso marker="#update_logger_config-1">
<c>update_logger_config/1</c></seealso>, or, if a more
@@ -658,21 +694,25 @@ start(_, []) ->
<func>
<name name="set_logger_config" arity="2"/>
- <fsummary>Add or update configuration data for the logger.</fsummary>
+ <fsummary>Add or update configuration data for the logger part
+ of Logger.</fsummary>
<desc>
- <p>Add or update configuration data for the logger. If the
- given <c><anno>Key</anno></c> already exists, its associated
- value will be changed to <c><anno>Value</anno></c>. If it
- does not exist, it will be added.</p>
+ <p>Add or update configuration data for the logger part of
+ Logger. If the given <c><anno>Key</anno></c> already exists,
+ its associated value will be changed
+ to <c><anno>Value</anno></c>. If it does not exist, it will
+ be added.</p>
</desc>
</func>
<func>
<name name="update_logger_config" arity="1"/>
- <fsummary>Update configuration data for the logger.</fsummary>
+ <fsummary>Update configuration data for the logger part of
+ Logger.</fsummary>
<desc>
- <p>Update configuration data for the logger. This function
- behaves as if it was implemented as follows:</p>
+ <p>Update configuration data for the logger part of
+ Logger. This function behaves as if it was implemented as
+ follows:</p>
<code type="erl">
{ok,Old} = logger:get_logger_config(),
logger:set_logger_config(maps:merge(Old,Config)).
@@ -697,7 +737,7 @@ logger:set_logger_config(maps:merge(Old,Config)).
</seealso>, then do the merge before writing the new
configuration back with this function.</p>
<p>If a key is removed compared to the current configuration,
- and the key is know by Logger, the default value is used. If
+ and the key is known by Logger, the default value is used. If
it is a custom key, then it is up to the handler
implementation if the value is removed or a default value is
inserted.</p>
diff --git a/lib/kernel/doc/src/logger_chapter.xml b/lib/kernel/doc/src/logger_chapter.xml
index 4232429589..21b460e72a 100644
--- a/lib/kernel/doc/src/logger_chapter.xml
+++ b/lib/kernel/doc/src/logger_chapter.xml
@@ -36,14 +36,14 @@
this API can be used as is, or it can be customized to suite
specific needs.</p>
<p>It consists of two parts - the <em>logger</em> part and the
- <em>handler</em> part. The logger will forward log events to one
- or more handler(s).</p>
+ <em>handler</em> part. The logger part forwards log events to
+ one or more handler(s).</p>
<image file="logger_arch.png">
<icaption>Conceptual overview</icaption>
</image>
- <p><em>Filters</em> can be added to the logger and to each
+ <p><em>Filters</em> can be added to the logger part and to each
handler. The filters decide if an event is to be forwarded or
not, and they can also modify all parts of the log event.</p>
@@ -121,10 +121,10 @@
<code>log(Log, Config) -> ok</code>
- <p>A handler is called by the logger backend after filtering on
- logger level and on handler level for the handler which is
- about to be called. The function call is done on the client
- process, and it is up to the handler implementation if other
+ <p>The handler callback is called after filtering on logger
+ level and on handler level for the handler in
+ question. The function call is done on the client process,
+ and it is up to the handler implementation if other
processes are to be involved or not.</p>
<p>Multiple instances of the same handler can be
@@ -134,7 +134,7 @@
<tag><marker id="Filter"/>Filter</tag>
<item>
- <p>Filters can be set on the logger or on a handler. Logger
+ <p>Filters can be set on the logger part, or on a handler. Logger
filters are applied first, and if passed, the handler filters
for each handler are applied. The handler callback is only
called if all handler filters for the handler in question also
@@ -145,7 +145,7 @@
<code>{fun((Log,Extra) -> Log | stop | ignore), Extra}</code>
<p>The configuration parameter <c>filter_default</c>
- specifies the behavior if all filters return <c>ignore</c>.
+ specifies the behaviour if all filters return <c>ignore</c>.
<c>filter_default</c> is by default set to <c>log</c>.</p>
<p>The <c>Extra</c> parameter may contain any data that the
@@ -250,52 +250,58 @@
<p>Logger can be configured either when the system starts through
<seealso marker="config">configuration parameters</seealso>,
- or at run-time by using the <seealso marker="logger">logger</seealso>
+ or at run-time by using the <seealso marker="logger">logger(3)</seealso>
API. The recommended approach is to do the initial configuration in
the <c>sys.config</c> file and then use the API when some configuration
- has to be changed at run-time, such as the logging level.</p>
+ has to be changed at run-time, such as the log level.</p>
<section>
- <title>Application configuration parameters</title>
+ <title>Kernel Configuration Parameters</title>
<p>Logger is best configured by using the configuration parameters
- of kernel. There are three possible configuration parameters:
+ of Kernel. There are four possible configuration parameters:
<seealso marker="#logger"><c>logger</c></seealso>,
<seealso marker="kernel_app#logger_level"><c>logger_level</c></seealso>,
<seealso marker="kernel_app#logger_sasl_compatible"><c>logger_sasl_compatible</c></seealso> and
<seealso marker="kernel_app#logger_log_progress"><c>logger_log_progress</c></seealso>.
- logger_level, logger_sasl_compatible and logger_log_progress are described in the
+ <c>logger_level</c>, <c>logger_sasl_compatible</c> and <c>logger_log_progress</c> are described in the
<seealso marker="kernel_app#configuration">Kernel Configuration</seealso>,
while <c>logger</c> is described below.</p>
- <section>
+
<marker id="logger"/>
- <title>logger</title>
- <p>The <c>logger</c> application configuration parameter is used to configure
- three different logger aspects; handlers, logger filters and module levels.
+ <p><em>logger</em></p>
+ <p>The application configuration parameter <c>logger</c> is used to configure
+ three different Logger aspects; handlers, logger filters and module levels.
The configuration is a list containing tagged tuples that look like this:</p>
<taglist>
<tag><c>DisableHandler = {handler,default,undefined}</c></tag>
- <item>Disable the default handler. This will allow another application
+ <item>
+ <p>Disable the default handler. This allows another application
to add its own default handler. See <seealso marker="logger#add_handlers/1">
- <c>logger:add_handlers/1</c></seealso> for more details.</item>
+ <c>logger:add_handlers/1</c></seealso> for more details.</p>
+ <p>Only one entry of this option is allowed.</p></item>
<tag><c>AddHandler = {handler,HandlerId,Module,HandlerConfig}</c></tag>
- <item>Add a handler as if <seealso marker="logger:add_handler/3">
- <c>logger:add_handler(HandlerId,Module,HandlerConfig)</c></seealso> had been
- called.</item>
- <tag><c>Filters = {filters, FilterDefault, [Filter]}</c><br/>
+ <item>
+ <p>Add a handler as if <seealso marker="logger:add_handler/3">
+ <c>logger:add_handler(HandlerId,Module,HandlerConfig)</c></seealso> is
+ called.</p>
+ <p>It is allowed to have multiple entries of this option.</p></item>
+ <tag><c>Filters = {filters, default, [Filter]}</c><br/>
<c>FilterDefault = log | stop</c><br/>
<c>Filter = {FilterId, {FilterFun, FilterConfig}}</c></tag>
- <item>Add the specified <seealso marker="logger#add_logger_filter/2">
- logger filters</seealso>. Only one entry is allowed of this option.</item>
- <tag><c>ModuleLevel</c></tag>
- <item><c>{module_level, Level, [Module]}</c>,
- this option configures the <seealso marker="logger#set_module_level/2">
- module log level</seealso> to be used. It is possible to have multiple
- <c>module_level</c> entries.</item>
+ <item>
+ <p>Add the specified <seealso marker="logger#add_logger_filter/2">
+ logger filters</seealso>.</p>
+ <p>Only one entry of this option is allowed.</p></item>
+ <tag><c>ModuleLevel = {module_level, Level, [Module]}</c></tag>
+ <item>
+ <p>This option configures <seealso marker="logger#set_module_level/2">
+ module log level</seealso>.</p>
+ <p>It is allowed to have multiple entries of this option.</p></item>
</taglist>
<p>Examples:</p>
<list>
<item>
- <p>Output logs into a the file &quot;logs/erlang.log&quot;</p>
+ <p>Output logs into the file &quot;logs/erlang.log&quot;</p>
<code>
[{kernel,
[{logger,
@@ -338,7 +344,6 @@
</code>
</item>
</list>
- </section>
</section>
<section>
@@ -441,36 +446,30 @@
<c>error_logger</c> in the following ways:</p>
<taglist>
- <tag>Legacy event handlers</tag>
- <item>
- <p>To use event handlers written for <c>error_logger</c>, just
- add your event handler with</p>
- <code>
-error_logger:add_report_handler/1,2.
- </code>
- <p>This will automatically start the <c>error_logger</c>
- event manager, and add <c>error_logger</c> as a
- handler to <c>logger</c>, with configuration</p>
-<code>
-#{level=>info,
- filter_default=>log,
- filters=>[]}.
-</code>
- <p>Note that this handler will ignore events that do not
- originate from the old <c>error_logger</c> API, or from
- within OTP. This means that if your code uses the logger API
- for logging, then your log events will be discarded by this
- handler.</p>
- <p>Also note that <c>error_logger</c> is not overload
- protected.</p>
- </item>
- <tag>Logger API</tag>
+ <tag>API for Logging</tag>
<item>
<p>The old <c>error_logger</c> API still exists, but should
only be used by legacy code. It will be removed in a later
release.</p>
+ <p>Calls
+ to <seealso marker="error_logger#error_report-1">
+ <c>error_logger:error_report/1,2</c></seealso>,
+ <seealso marker="error_logger#error_msg-1">
+ <c>error_logger:error_msg/1,2</c></seealso>, and
+ corresponding functions for warning and info messages, are
+ all forwarded to Logger as calls
+ to <seealso marker="logger#log-3">
+ <c>logger:log(Level,Report,Metadata)</c></seealso>.</p>
+ <p><c>Level = error | warning | info</c> and is taken
+ from the function name. <c>Report</c> contains the actual
+ log message, and <c>Metadata</c> contains additional
+ information which can be used for creating backwards
+ compatible events for legacy <c>error_logger</c> event
+ handlers, see
+ section <seealso marker="#legacy_event_handlers">Legacy
+ Event Handlers</seealso>.</p>
</item>
- <tag>Output format</tag>
+ <tag>Output Format</tag>
<item>
<p>To get log events on the same format as produced
by <c>error_logger_tty_h</c> and <c>error_logger_file_h</c>,
@@ -478,13 +477,13 @@ error_logger:add_report_handler/1,2.
configuration parameter <c>legacy_header=>true</c>. This is
also the default.</p>
</item>
- <tag>Default format of log events from OTP</tag>
+ <tag>Default Format of Log Events from OTP</tag>
<item>
<p>By default, all log events originating from within OTP,
except the former so called "SASL reports", look the same as
before.</p>
</item>
- <tag>SASL reports</tag>
+ <tag>SASL Reports</tag>
<item>
<p>By SASL reports we mean supervisor reports, crash reports
and progress reports.</p>
@@ -494,32 +493,63 @@ error_logger:add_report_handler/1,2.
named <c>sasl_report_tty_h</c>
and <c>sasl_report_file_h</c>.</p>
<p>The destination of these log events were configured by
- environment variables for the SASL application.</p>
+ <seealso marker="sasl:sasl_app#deprecated_error_logger_config">SASL
+ configuration parameters</seealso>.</p>
<p>Due to the specific event handlers, the output format
slightly differed from other log events.</p>
<p>As of OTP-21, the concept of SASL reports is removed,
- meaning that the default behavior is as follows:</p>
+ meaning that the default behaviour is as follows:</p>
<list>
<item>Supervisor reports, crash reports and progress reports
are no longer connected to the SASL application.</item>
<item>Supervisor reports and crash reports are logged by
default.</item>
<item>Progress reports are not logged by default, but can be
- enabled with the kernel environment
- variable <c>logger_log_progress</c>.</item>
+ enabled with the Kernel configuration
+ parameter <seealso marker="kernel_app#logger_log_progress">
+ <c>logger_log_progress</c></seealso>.</item>
<item>The output format is the same for all log
events.</item>
</list>
- <p>If the old behavior is preferred, the kernel environment
- variable <c>logger_sasl_compatible</c> can be set
- to <c>true</c>. The old SASL environment variables can then
- be used as before, and the SASL reports will only be printed
- if the SASL application is running - through a second log
- handler named <c>sasl_h</c>.</p>
+ <p>If the old behaviour is preferred, the Kernel configuation
+ parameter <seealso marker="kernel_app:logger_sasl_compatible">
+ <c>logger_sasl_compatible</c></seealso> can be set
+ to <c>true</c>. The
+ old <seealso marker="sasl:sasl_app#deprecated_error_logger_config">SASL
+ configuration parameters</seealso> can then be used as
+ before, and the SASL reports will only be printed if the
+ SASL application is running, through a second log handler
+ named <c>sasl_h</c>.</p>
<p>All SASL reports have a metadata
field <c>domain=>[beam,erlang,otp,sasl]</c>, which can be
used, for example, by filters to stop or allow the
events.</p>
+ <p>See the <seealso marker="sasl:error_logging">SASL User's
+ Guide</seealso> for more information about the old SASL
+ error logging functionality.</p>
+ </item>
+ <tag><marker id="legacy_event_handlers"/>Legacy Event Handlers</tag>
+ <item>
+ <p>To use event handlers written for <c>error_logger</c>, just
+ add your event handler with</p>
+ <code>
+error_logger:add_report_handler/1,2.
+ </code>
+ <p>This will automatically start the <c>error_logger</c>
+ event manager, and add <c>error_logger</c> as a
+ handler to <c>logger</c>, with configuration</p>
+<code>
+#{level=>info,
+ filter_default=>log,
+ filters=>[]}.
+</code>
+ <p>Notice that this handler will ignore events that do not
+ originate from the old <c>error_logger</c> API, or from
+ within OTP. This means that if your code uses the Logger API
+ for logging, then your log events will be discarded by this
+ handler.</p>
+ <p>Also notice that <c>error_logger</c> is not overload
+ protected.</p>
</item>
</taglist>
</section>
@@ -535,14 +565,14 @@ error_logger:add_report_handler/1,2.
converting the report to a format string and arguments. The
handler might also do a custom conversion if the default format
is not desired.</p>
- <p><c>logger</c> does, to a certain extent, check its input data
+ <p>Logger does, to a certain extent, check its input data
before forwarding a log event to the handlers, but it does not
evaluate conversion funs or check the validity of format strings
and arguments. This means that any filter or handler must be
careful when formatting the data of a log event, making sure
that it does not crash due to bad input data or faulty
callbacks.</p>
- <p>If a filter or handler still crashes, logger will remove the
+ <p>If a filter or handler still crashes, Logger will remove the
filter or handler in question from the configuration, and then
print a short error message on the console. A debug event
containing the crash reason and other details is also issued,
@@ -552,13 +582,13 @@ error_logger:add_report_handler/1,2.
<section>
<title>Example: add a handler to log debug events to file</title>
- <p>When starting an erlang node, the default behavior is that all
+ <p>When starting an erlang node, the default behaviour is that all
log events with level info and above are logged to the
console. In order to also log debug events, you can either
change the global log level to <c>debug</c> or add a separate
handler to take care of this. In this example we will add a new
handler which prints the debug events to a separate file.</p>
- <p>First, we add an instance of logger_std_h with
+ <p>First, we add an instance of <c>logger_std_h</c> with
type <c>{file,File}</c>, and we set the handler's level
to <c>debug</c>:</p>
<pre>
@@ -575,9 +605,9 @@ ok</pre>
#Fun&lt;erl_eval.12.98642416>
4> <input>logger:add_handler_filter(debug_handler,allow_debug,{Fun,[]}).</input>
ok</pre>
- <p>And finally, we need to make sure that the logger itself allows
+ <p>And finally, we need to make sure that Logger itself allows
debug events. This can either be done by setting the global
- logger level:</p>
+ log level:</p>
<pre>
5> <input>logger:set_logger_config(level,debug).</input>
ok</pre>
@@ -599,21 +629,22 @@ adding_handler(logger:handler_id(),logger:config()) -> {ok,logger:config()} | {e
removing_handler(logger:handler_id(),logger:config()) -> ok
changing_config(logger:handler_id(),logger:config(),logger:config()) -> {ok,logger:config()} | {error,term()}
</code>
- <p>When logger:add_handler(Id,Module,Config) is called, logger
- will first call Module:adding_handler(Id,Config), and if it
- returns {ok,NewConfig} the NewConfig is written to the
+ <p>When <c>logger:add_handler(Id,Module,Config)</c> is called, Logger
+ will first call <c>Module:adding_handler(Id,Config)</c>, and if it
+ returns <c>{ok,NewConfig}</c>, <c>NewConfig</c> is written to the
configuration database. After this, the handler may receive log
- events as calls to Module:log/2.</p>
+ events as calls to <c>Module:log/2</c>.</p>
<p>A handler can be removed by calling
- logger:remove_handler(Id). logger will call
- Module:removing_handler(Id,Config), and then remove the handler's
- configuration from the configuration database.</p>
- <p>When logger:set_handler_config is called, logger calls
- Module:changing_config(Id,OldConfig,NewConfig). If this function
- returns ok, the NewConfig is written to the configuration
- database.</p>
-
- <p>A simple handler which prints to the console could be
+ <c>logger:remove_handler(Id)</c>. Logger will call
+ <c>Module:removing_handler(Id,Config)</c>, and then remove the
+ handler's configuration from the configuration database.</p>
+ <p>When <c>logger:set_handler_config/2,3</c>
+ or <c>logger:update_handler_config/2</c> are called, Logger
+ calls <c>Module:changing_config(Id,OldConfig,NewConfig)</c>. If
+ this function returns <c>{ok,NewConfig}</c>, <c>NewConfig</c> is
+ written to the configuration database.</p>
+
+ <p>A simple handler that prints to the console could be
implemented as follows:</p>
<code>
-module(myhandler).
@@ -720,7 +751,7 @@ do_log(Fd,Log,#{formatter:={FModule,FConfig}}) ->
and as long as the length of the message queue is lower, all log
requests are handled asynchronously. This simply means that the
process sending the log request (by calling a log function in the
- logger API) does not wait for a response from the handler but
+ Logger API) does not wait for a response from the handler but
continues executing immediately after the request (i.e. it will not
be affected by the time it takes the handler to print to the log
device). If the message queue grows larger than this value, however,
@@ -876,7 +907,14 @@ logger:add_handler(my_disk_log_h, logger_disk_log_h,
<section>
<title>See Also</title>
- <p><seealso marker="error_logger"><c>error_logger(3)</c></seealso>,
- <seealso marker="sasl:sasl_app"><c>SASL(6)</c></seealso></p>
+ <p>
+ <seealso marker="disk_log"><c>disk_log(3)</c></seealso>,
+ <seealso marker="error_logger"><c>error_logger(3)</c></seealso>,
+ <seealso marker="logger"><c>logger(3)</c></seealso>,
+ <seealso marker="logger_disk_log_h"><c>logger_disk_log_h(3)</c></seealso>,
+ <seealso marker="logger_filters"><c>logger_filters(3)</c></seealso>,
+ <seealso marker="logger_formatter"><c>logger_formatter(3)</c></seealso>,
+ <seealso marker="logger_std_h"><c>logger_std_h(3)</c></seealso>,
+ <seealso marker="sasl:sasl_app"><c>sasl(6)</c></seealso></p>
</section>
</chapter>
diff --git a/lib/kernel/doc/src/logger_disk_log_h.xml b/lib/kernel/doc/src/logger_disk_log_h.xml
index 440ae28e5d..20b49b8ca0 100644
--- a/lib/kernel/doc/src/logger_disk_log_h.xml
+++ b/lib/kernel/doc/src/logger_disk_log_h.xml
@@ -33,21 +33,21 @@
<file>logger_disk_log_h.xml</file>
</header>
<module>logger_disk_log_h</module>
- <modulesummary>A disk_log based handler for the Logger
- application.</modulesummary>
+ <modulesummary>A disk_log based handler for the Logger.</modulesummary>
<description>
- <p>This is a handler for the Logger application that offers circular
- (wrapped) logs by using the disk_log application. Multiple instances
- of this handler can be added to logger, and each instance will print to
+ <p>This is a handler for Logger that offers circular
+ (wrapped) logs by using <seealso marker="disk_log"><c>disk_log</c></seealso>.
+ Multiple instances
+ of this handler can be added to Logger, and each instance prints to
its own disk_log file, created with the name and settings specified in
the handler configuration.</p>
<p>The default standard handler,
<seealso marker="logger_std_h"><c>logger_std_h</c></seealso>, can be
- replaced by a disk_log handler at startup of the kernel application.
+ replaced by a disk_log handler at startup of the Kernel application.
See an example of this below.</p>
<p>The handler has an overload protection mechanism that will keep the handler
- process and the kernel application alive during a high load of log
+ process and the Kernel application alive during a high load of log
requests. How this feature works, and how to modify the configuration,
is described in the
<seealso marker="logger_chapter#overload_protection"><c>User's Guide</c>
@@ -121,7 +121,7 @@ logger:add_handler(my_disk_log_h, logger_disk_log_h,
#{filesync_repeat_interval => 1000}}).
</code>
<p>In order to use the disk_log handler instead of the default standard
- handler when starting en Erlang node, change the Kernel default logger to
+ handler when starting an Erlang node, change the Kernel default logger to
use disk_log. Example:</p>
<code type="none">
erl -kernel logger '[{handler,default,logger_disk_log_h,
@@ -141,6 +141,12 @@ erl -kernel logger '[{handler,default,logger_disk_log_h,
</funcs>
+ <section>
+ <title>See Also</title>
+ <p><seealso marker="logger"><c>logger(3)</c></seealso></p>
+ <p><seealso marker="logger_std_h"><c>logger_std_h(3)</c></seealso></p>
+ <p><seealso marker="disk_log"><c>disk_log(3)</c></seealso></p>
+ </section>
</erlref>
diff --git a/lib/kernel/doc/src/logger_formatter.xml b/lib/kernel/doc/src/logger_formatter.xml
index 370d61d338..ee43634cf9 100644
--- a/lib/kernel/doc/src/logger_formatter.xml
+++ b/lib/kernel/doc/src/logger_formatter.xml
@@ -39,7 +39,8 @@
<p>Each log handler has a configured formatter specified as a
module and a configuration term. The purpose of the formatter is
to translate the log events to a final printable string
- (<c>unicode:chardata()</c>) which can be written to the output
+ (<seealso marker="stdlib:unicode#type-chardata"><c>unicode:chardata()</c>
+ </seealso>) which can be written to the output
device of the handler.</p>
<p><c>logger_formatter</c> is the default formatter used by
Logger.</p>
@@ -47,7 +48,8 @@
<section>
<title>Configuration</title>
- <p>The configuration term for <c>logger_formatter</c> is a map,
+ <p>The configuration term for <c>logger_formatter</c> is a
+ <seealso marker="stdlib:maps">map</seealso>,
and the following keys can be set as configuration
parameters:</p>
<taglist>
@@ -55,7 +57,7 @@
<item>
<p>A positive integer representing the value of the option
with the same name to be used when calling
- <seealso marker="stdlib:io_lib#format-3">io_lib:format/3</seealso>.
+ <seealso marker="stdlib:io_lib#format-3"><c>io_lib:format/3</c></seealso>.
This value limits the total number of characters printed
for each log event. Notice that this is a soft limit. For a
hard truncation limit, see option <c>max_size</c>.</p>
@@ -99,7 +101,7 @@
added by the <c>template</c> parameter are not replaced.</p>
<p>Default is <c>true</c>.</p>
</item>
- <tag><c>legacy_header = boolen()</c></tag>
+ <tag><c>legacy_header = boolean()</c></tag>
<item>
<p>If set to <c>true</c> a header field is added to
logger_formatter's part of <c>Metadata</c>. The value of
@@ -181,8 +183,8 @@
to <c>"+02:00"</c>.</p>
<p>The default value is an empty string, meaning that
timestamps are displayed in local time. However, for
- backwards compatibility, if the SASL environment
- variable <seealso marker="sasl:sasl_app#utc_log">
+ backwards compatibility, if the SASL configuration
+ parameter <seealso marker="sasl:sasl_app#utc_log">
<c>utc_log</c></seealso><c>=true</c>, the default is
changed to <c>"Z"</c>, meaning that timestamps are displayed
in UTC.</p>
@@ -206,28 +208,42 @@
?LOG_ERROR("name: ~p~nexit_reason: ~p",[my_name,"It crashed"])</code>
<taglist>
- <tag><c>legacy_header=true</c></tag>
+ <tag><c>legacy_header=true, single_line=false</c></tag>
<item>
<p>Default template: <c>[{logger_formatter,header},"\n",msg,"\n"]</c></p>
<p>Example log entry:</p>
<code type="none">
-2018-05-16T11:55:50.448382+02:00 error:
+=ERROR REPORT==== 17-May-2018::18:30:19.453447 ===
name: my_name
exit_reason: "It crashed"</code>
- <p>Notice that all eight levels might occur in the heading,
+ <p>Notice that all eight levels can occur in the heading,
not only <c>ERROR</c>, <c>WARNING</c> or <c>INFO</c> as the
old <c>error_logger</c> produced. And microseconds are
added at the end of the timestamp.</p>
</item>
- <tag><c>single_line=true</c></tag>
+ <tag><c>legacy_header=true, single_line=true</c></tag>
+ <item>
+ <p>Default template: <c>[{logger_formatter,header},"\n",msg,"\n"]</c></p>
+
+ <p>Notice that the template is here the same as
+ for <c>single_line=false</c>, but the resulting log entry
+ differs in that there is only one line after the
+ heading:</p>
+ <code type="none">
+=ERROR REPORT==== 17-May-2018::18:31:06.952665 ===
+name: my_name, exit_reason: "It crashed"</code>
+ </item>
+
+ <tag><c>legacy_header=false, single_line=true</c></tag>
<item>
<p>Default template: <c>[time," ",level,": ",msg,"\n"]</c></p>
<p>Example log entry:</p>
- <code type="none">2018-05-16T11:55:50.448382+02:00 error: name: my_name, exit_reason: "It crashed"</code>
+ <code type="none">
+2018-05-17T18:31:31.152864+02:00 error: name: my_name, exit_reason: "It crashed"</code>
</item>
<tag><c>legacy_header=false, single_line=false</c></tag>
@@ -236,7 +252,7 @@ exit_reason: "It crashed"</code>
<p>Example log entry:</p>
<code type="none">
-2018-05-16T11:55:50.448382+02:00 error:
+2018-05-17T18:32:20.105422+02:00 error:
name: my_name
exit_reason: "It crashed"</code>
</item>
diff --git a/lib/kernel/doc/src/logger_std_h.xml b/lib/kernel/doc/src/logger_std_h.xml
index bf23d874c8..a4f2848037 100644
--- a/lib/kernel/doc/src/logger_std_h.xml
+++ b/lib/kernel/doc/src/logger_std_h.xml
@@ -33,17 +33,17 @@
<file>logger_std_h.xml</file>
</header>
<module>logger_std_h</module>
- <modulesummary>Default handler for the Logger application.</modulesummary>
+ <modulesummary>Default handler for Logger.</modulesummary>
<description>
- <p>This is the default handler for the Logger
- application. Multiple instances of this handler can be added to
- logger, and each instance will print logs to <c>standard_io</c>,
+ <p>This is the default handler for Logger.
+ Multiple instances of this handler can be added to
+ Logger, and each instance will print logs to <c>standard_io</c>,
<c>standard_error</c> or to file. The default instance that starts
- with kernel is named <c>default</c> - which is the name to be used
+ with Kernel is named <c>default</c> - which is the name to be used
for reconfiguration.</p>
<p>The handler has an overload protection mechanism that will keep the handler
- process and the kernel application alive during a high load of log
+ process and the Kernel application alive during a high load of log
requests. How this feature works, and how to modify the configuration,
is described in the
<seealso marker="logger_chapter#overload_protection"><c>User's Guide</c>
@@ -104,7 +104,7 @@ logger:add_handler(my_standard_h, logger_std_h,
filesync_repeat_interval => 1000}}).
</code>
<p>In order to configure the default handler (that starts initially with
- the kernel application) to log to file instead of <c>standard_io</c>,
+ the Kernel application) to log to file instead of <c>standard_io</c>,
change the Kernel default logger to use a file. Example:</p>
<code type="none">
erl -kernel logger '[{handler,default,logger_std_h,
@@ -127,6 +127,11 @@ erl -kernel logger '[{handler,default,logger_std_h,
</funcs>
+ <section>
+ <title>See Also</title>
+ <p><seealso marker="logger"><c>logger(3)</c></seealso></p>
+ <p><seealso marker="logger_disk_log_h"><c>logger_disk_log_h(3)</c></seealso></p>
+ </section>
</erlref>
diff --git a/lib/runtime_tools/doc/src/LTTng.xml b/lib/runtime_tools/doc/src/LTTng.xml
index 93937b3fdc..4114542c74 100644
--- a/lib/runtime_tools/doc/src/LTTng.xml
+++ b/lib/runtime_tools/doc/src/LTTng.xml
@@ -111,7 +111,7 @@ $ make </code>
<p><em>process_register</em></p>
<list type="bulleted">
<item><c>pid : string</c> :: Process ID. Ex. <c>"&lt;0.131.0&gt;"</c></item>
- <item><c>name : string</c> :: Registered name. Ex. <c>"error_logger"</c></item>
+ <item><c>name : string</c> :: Registered name. Ex. <c>"logger"</c></item>
<item><c>type : string</c> :: <c>"register" | "unregister"</c></item>
</list>
<p>Example:</p>
diff --git a/lib/sasl/doc/src/error_logging.xml b/lib/sasl/doc/src/error_logging.xml
index 4b2c960bbb..44506ffdad 100644
--- a/lib/sasl/doc/src/error_logging.xml
+++ b/lib/sasl/doc/src/error_logging.xml
@@ -32,22 +32,51 @@
<rev>B</rev>
<file>error_logging.xml</file>
</header>
+ <note>
+ <p>The SASL error logging concept desribed in this section is
+ deprecated since OTP-21, when the
+ new <seealso marker="kernel:logger_chapter">logging
+ API</seealso> was introduced.</p>
+ <p>The new default behaviour is that the SASL application no
+ longer affects which log events that are logged.
+ <seealso marker="#supervisor_report">Supervisor
+ reports</seealso> and <seealso marker="#crash_report">crash
+ reports</seealso> are logged via the default logger handler
+ which is setup by
+ Kernel. <seealso marker="#progress_report">Progress
+ reports</seealso> are by default not logged, but can be enabled
+ by setting the Kernel configuration
+ parameter <seealso marker="kernel:kernel_app#logger_log_progress">
+ <c>logger_log_progress</c></seealso> to <c>true</c>.</p>
+ <p>The old SASL error logging behaviour can be re-enabled by setting the
+ Kernel configuration
+ parameter <seealso marker="kernel:kernel_app#logger_sasl_compatible">
+ <c>logger_sasl_compatible</c></seealso> to <c>true</c>.</p>
+ <p>The mechanism
+ for <seealso marker="#multi_file_logging">multi-file error report
+ logging</seealso> as described in this section is also kept for
+ backwards compatibility. However, the new logging API also
+ introduces <seealso marker="kernel:logger_disk_log_h">
+ <c>logger_disk_log_h(3)</c></seealso>, which is a logger
+ handler that can print to multiple files
+ using <seealso marker="kernel:disk_log"><c>disk_log(3)</c></seealso>.</p>
+ </note>
+
+ <section>
+ <title>SASL reports</title>
<p>The SASL application introduces three types of reports:</p>
<list type="bulleted">
<item>Supervisor report</item>
<item>Progress report</item>
<item>Crash report</item>
</list>
- <p>When the SASL application is started, it adds a handler that
- formats and writes these reports, as specified in the configuration
- parameters for SASL, that is, the environment variables
- in the SASL application specification, which is found in the
- <c>.app</c> file of SASL. For details, see the
- <seealso marker="sasl_app"><c>sasl(6)</c></seealso> application in the
- Reference Manual and the <seealso marker="kernel:app"><c>app(4)</c></seealso>
- file in the Kernel Reference Manual.</p>
+ <p>When the SASL application is started, it adds a logger handler
+ that formats and writes these reports, as specified in
+ the <seealso marker="sasl_app#deprecated_error_logger_config">configuration
+ parameters for SASL</seealso></p>
<section>
+ <marker id="supervisor_report"/>
<title>Supervisor Report</title>
<p>A supervisor report is issued when a supervised child terminates
unexpectedly. A supervisor report contains the following
@@ -68,6 +97,7 @@
</section>
<section>
+ <marker id="progress_report"/>
<title>Progress Report</title>
<p>A progress report is issued when a supervisor starts or
restarts a child. A progress report contains the following items:</p>
@@ -82,6 +112,7 @@
</section>
<section>
+ <marker id="crash_report"/>
<title>Crash Report</title>
<p>Processes started with functions
<seealso marker="stdlib:proc_lib#spawn/1"><c>proc_lib:spawn</c></seealso> or
@@ -105,6 +136,7 @@
crash. The information gathered is the same as the information
for Crasher, described in the previous item.</p></item>
</taglist>
+ </section>
<section>
<title>Example</title>
@@ -163,6 +195,7 @@
</section>
<section>
+ <marker id="multi_file_logging"/>
<title>Multi-File Error Report Logging</title>
<p>Multi-file error report logging is used to store error messages
received by <c>error_logger</c>. The error messages
@@ -171,7 +204,8 @@
of files exist at the same time. The logging is very fast, as
each error message is written as a binary term.</p>
<p>For more details, see the
- <seealso marker="sasl_app"><c>sasl(6)</c></seealso>
+ <seealso marker="sasl_app#deprecated_error_logger_config">
+ <c>sasl(6)</c></seealso>
application in the Reference Manual.</p>
</section>
diff --git a/lib/sasl/doc/src/sasl_app.xml b/lib/sasl/doc/src/sasl_app.xml
index 26b9bece2a..eb1e87d9a3 100644
--- a/lib/sasl/doc/src/sasl_app.xml
+++ b/lib/sasl/doc/src/sasl_app.xml
@@ -90,20 +90,22 @@
</section>
<section>
+ <marker id="deprecated_error_logger_config"/>
<title>Deprecated Error Logger Event Handlers and Configuration</title>
<p>In OTP-21, a new API for logging was added to Erlang/OTP. The
old <c>error_logger</c> event manager, and event handlers
running on this manager, will still work, but they are not used
by default.</p>
<p>The error logger event handlers <c>sasl_report_tty_h</c>
- and <c>sasl_report_file_h</c>, were earliger used for printing
+ and <c>sasl_report_file_h</c>, were earlier used for printing
the so called SASL reports, i.e. <em>supervisor
reports</em>, <em>crash reports</em>, and <em>progress
- reports</em>. These reports are now also printed by the standard
+ reports</em>. These reports are now also printed by the default
logger handler started by the Kernel application. Progress
reports are by default stopped by a filter, but can easily be
added by setting the Kernel configuration
- parameter <seealso marker="kernel:kernel_app#logger_log_progress"><c>logger_log_progress=true</c></seealso>.</p>
+ parameter <seealso marker="kernel:kernel_app#logger_log_progress">
+ <c>logger_log_progress=true</c></seealso>.</p>
<p>If the old error logger event handlers are still desired, they
must be added by
calling <c>error_logger:add_report_handler/1,2</c>.</p>
@@ -218,6 +220,7 @@
<title>See Also</title>
<p><seealso marker="alarm_handler"><c>alarm_handler(3)</c></seealso>,
<seealso marker="kernel:error_logger"><c>error_logger(3)</c></seealso>,
+ <seealso marker="kernel:logger"><c>logger(3)</c></seealso>,
<seealso marker="stdlib:log_mf_h"><c>log_mf_h(3)</c></seealso>,
<seealso marker="rb"><c>rb(3)</c></seealso>,
<seealso marker="release_handler"><c>release_handler(3)</c></seealso>,
diff --git a/lib/stdlib/doc/src/gen_event.xml b/lib/stdlib/doc/src/gen_event.xml
index 012737c390..51378a6b73 100644
--- a/lib/stdlib/doc/src/gen_event.xml
+++ b/lib/stdlib/doc/src/gen_event.xml
@@ -458,8 +458,7 @@ gen_event:stop -----> Module:terminate/2
with the expected reason. Any other reason than <c>normal</c>,
<c>shutdown</c>, or <c>{shutdown,Term}</c> causes an
error report to be issued using
- <seealso marker="kernel:error_logger#format/2">
- <c>error_logger:format/2</c></seealso>.
+ <seealso marker="kernel:logger"><c>logger(3)</c></seealso>.
The default <c>Reason</c> is <c>normal</c>.</p>
<p><c>Timeout</c> is an integer greater than zero that
specifies how many milliseconds to wait for the event manager to
diff --git a/lib/stdlib/doc/src/gen_server.xml b/lib/stdlib/doc/src/gen_server.xml
index da74e793e6..27edbc8de7 100644
--- a/lib/stdlib/doc/src/gen_server.xml
+++ b/lib/stdlib/doc/src/gen_server.xml
@@ -486,8 +486,7 @@ gen_server:abcast -----> Module:handle_cast/2
with the expected reason. Any other reason than <c>normal</c>,
<c>shutdown</c>, or <c>{shutdown,Term}</c> causes an
error report to be issued using
- <seealso marker="kernel:error_logger#format/2">
- <c>error_logger:format/2</c></seealso>.
+ <seealso marker="kernel:logger"><c>logger(3)</c></seealso>.
The default <c>Reason</c> is <c>normal</c>.</p>
<p><c>Timeout</c> is an integer greater than zero that
specifies how many milliseconds to wait for the server to
@@ -861,8 +860,7 @@ gen_server:abcast -----> Module:handle_cast/2
<c>shutdown</c>, or <c>{shutdown,Term}</c>, the <c>gen_server</c>
process is assumed to terminate because of an error and
an error report is issued using
- <seealso marker="kernel:error_logger#format/2">
- <c>error_logger:format/2</c></seealso>.</p>
+ <seealso marker="kernel:logger"><c>logger(3)</c></seealso>.</p>
</desc>
</func>
</funcs>
diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml
index e918e83df7..a808d3af55 100644
--- a/lib/stdlib/doc/src/gen_statem.xml
+++ b/lib/stdlib/doc/src/gen_statem.xml
@@ -1778,7 +1778,7 @@ handle_event(_, _, State, Data) ->
with the expected reason. Any other reason than <c>normal</c>,
<c>shutdown</c>, or <c>{shutdown,Term}</c> causes an
error report to be issued through
- <seealso marker="kernel:error_logger#format/2"><c>error_logger:format/2</c></seealso>.
+ <seealso marker="kernel:logger"><c>logger(3)</c></seealso>.
The default <c><anno>Reason</anno></c> is <c>normal</c>.
</p>
<p>
@@ -2286,7 +2286,7 @@ init(Args) -> erlang:error(not_implemented, [Args]).</pre>
<c>shutdown</c>, or <c>{shutdown,Term}</c>,
the <c>gen_statem</c> is assumed to terminate because of an error
and an error report is issued using
- <seealso marker="kernel:error_logger#format/2"><c>error_logger:format/2</c></seealso>.
+ <seealso marker="kernel:logger"><c>logger(3)</c></seealso>.
</p>
</desc>
</func>
diff --git a/lib/stdlib/doc/src/proc_lib.xml b/lib/stdlib/doc/src/proc_lib.xml
index cb152d1935..c4fdf972e4 100644
--- a/lib/stdlib/doc/src/proc_lib.xml
+++ b/lib/stdlib/doc/src/proc_lib.xml
@@ -59,18 +59,16 @@
<p>When a process that is started using <c>proc_lib</c> terminates
abnormally (that is, with another exit reason than <c>normal</c>,
<c>shutdown</c>, or <c>{shutdown,Term}</c>), a <em>crash report</em>
- is generated, which is written to terminal by the default SASL
- event handler. That is, the crash report is normally only visible
- if the SASL application is started; see
- <seealso marker="sasl:sasl_app"><c>sasl(6)</c></seealso> and section
- <seealso marker="sasl:error_logging">SASL Error Logging</seealso>
- in the SASL User's Guide.</p>
+ is generated, which is written to terminal by the default logger
+ handler setup by Kernel. For more information about how crash reports
+ were logged before OTP-21, see <seealso marker="sasl:error_logging">
+ SASL Error Logging</seealso> in the SASL User's Guide.</p>
<p>Unlike in "plain Erlang", <c>proc_lib</c> processes will not generate
<em>error reports</em>, which are written to the terminal by the
- emulator and do not require SASL to be started. All exceptions are
+ emulator. All exceptions are
converted to <em>exits</em> which are ignored by the default
- <c>error_logger</c> handler.</p>
+ <c>logger</c> handler.</p>
<p>The crash report contains the previously stored information, such
as ancestors and initial function, the termination reason, and
@@ -115,12 +113,22 @@
<name name="format" arity="2"/>
<fsummary>Format a crash report.</fsummary>
<desc>
- <p>This function can be used by a user-defined event handler to
+ <note>
+ <p>This function is deprecated in the sense that
+ the <c>error_logger</c> is no longer the preferred
+ interface for logging in Erlang/OTP. A
+ new <seealso marker="kernel:logger_chapter">logging
+ API</seealso> was added in OTP-21, but
+ legacy <c>error_logger</c> handlers may still be used. New
+ logger handlers do not need to used this function, since
+ the formatting callback (<c>report_cb</c>) is included as
+ metadata in the log event.</p>
+ </note>
+ <p>This function can be used by a user-defined legacy
+ <c>error_logger</c> event handler to
format a crash report. The crash report is sent using
- <seealso marker="kernel:error_logger#error_report/2">
- <c>error_logger:error_report(crash_report,
- <anno>CrashReport</anno>)</c></seealso>.
- That is, the event to be handled is of the format
+ <seealso marker="kernel:logger">
+ <c>logger(3)</c></seealso>, and the event to be handled is of the format
<c>{error_report, GL, {Pid, crash_report,
<anno>CrashReport</anno>}}</c>,
where <c>GL</c> is the group leader pid of process
@@ -132,7 +140,19 @@
<name name="format" arity="3"/>
<fsummary>Format a crash report.</fsummary>
<desc>
- <p>This function can be used by a user-defined event handler to
+ <note>
+ <p>This function is deprecated in the sense that
+ the <c>error_logger</c> is no longer the preferred
+ interface for logging in Erlang/OTP. A
+ new <seealso marker="kernel:logger_chapter">logging
+ API</seealso> was added in OTP-21, but
+ legacy <c>error_logger</c> handlers may still be used. New
+ logger handlers do not need to used this function, since
+ the formatting callback (<c>report_cb</c>) is included as
+ metadata in the log event.</p>
+ </note>
+ <p>This function can be used by a user-defined legacy
+ <c>error_logger</c> event handler to
format a crash report. When <anno>Depth</anno> is specified as a
positive integer, it is used in the format string to
limit the output as follows: <c>io_lib:format("~P",
@@ -395,6 +415,8 @@ init(Parent) ->
<title>See Also</title>
<p><seealso marker="kernel:error_logger">
<c>error_logger(3)</c></seealso></p>
+ <p><seealso marker="kernel:logger">
+ <c>logger(3)</c></seealso></p>
</section>
</erlref>
diff --git a/system/doc/reference_manual/introduction.xml b/system/doc/reference_manual/introduction.xml
index afbdfa7434..c9f5fcb2db 100644
--- a/system/doc/reference_manual/introduction.xml
+++ b/system/doc/reference_manual/introduction.xml
@@ -48,7 +48,7 @@
System Principles</seealso></p>
<p>Starting and stopping, boot scripts, code loading,
<seealso marker="doc/system_principles:error_logging">
- error logging</seealso>,
+ logging</seealso>,
<seealso marker="doc/system_principles:create_target">
creating target systems</seealso></p>
</item>
diff --git a/system/doc/system_principles/error_logging.xml b/system/doc/system_principles/error_logging.xml
index c99d59ddb7..ee3d68d80e 100644
--- a/system/doc/system_principles/error_logging.xml
+++ b/system/doc/system_principles/error_logging.xml
@@ -39,80 +39,69 @@
<code type="none"><![CDATA[
=ERROR REPORT==== 9-Dec-2003::13:25:02 ===
Error in process <0.27.0> with exit value: {{badmatch,[1,2,3]},[{m,f,1},{shell,eval_loop,2}]}]]></code>
- <p>The error information is handled by the <em>error logger</em>, a
- system process registered as <c>error_logger</c>. This process
- receives all error messages from the Erlang runtime system as
- well as from the standard behaviours and different Erlang/OTP
- applications.</p>
+ <p>The error information is handled by Logger, which is part of
+ the Kernel application.</p>
<p>The exit reasons (such as <c>badarg</c>) used by
the runtime system are described in
<seealso marker="doc/reference_manual:errors#exit_reasons">
Errors and Error Handling</seealso>.</p>
- <p>For information about the process <c>error_logger</c> and its user
- interface (with the same name), see the
- <seealso marker="kernel:error_logger">error_logger(3)</seealso>
- manual page in Kernel. The system can be configured so that
- error information
- is written to file or to tty, or both. In addition, user-defined
- applications can send and format error information using
- <c>error_logger</c>.</p>
+ <p>For information about Logger and its user
+ interface, see the
+ <seealso marker="kernel:logger">logger(3)</seealso>
+ manual page and
+ the <seealso marker="kernel:logger_chapter">Logging</seealso>
+ section in the Kernel User's Guide. The system can be configured so that
+ log events are
+ written to file or to tty, or both. In addition, user-defined
+ applications can send and format log events using
+ Logger.</p>
</section>
<section>
- <title>SASL Error Logging</title>
+ <title>Log events from OTP behaviours</title>
<p>The standard behaviours (<c>supervisor</c>, <c>gen_server</c>,
- and so on) send progress and error information to <c>error_logger</c>.
- If the SASL application is started, this information is
- written to tty as well. For more information, see
+ and so on) send progress and error information to
+ Logger. Progress reports are by default not logged, but can be
+ enabled by setting the Kernel configuration
+ parameter <c>logger_log_progress</c> to true. Supervisor
+ reports, crash reports and other error and information reports
+ are by default logged through the log handler which is
+ set up when the Kernel application is started.</p>
+ <p>Prior to OTP-21, supervisor, crash, and progress reports were
+ only logged when the SASL application was running. This
+ behaviour can, for backwards compatibility, be enabled by
+ setting the Kernel configuration
+ parameter <c>logger_sasl_compatible</c> to <c>true</c>. For more
+ information, see
<seealso marker="sasl:error_logging">SASL Error Logging</seealso>
in the SASL User's Guide.</p>
<pre>
-% <input>erl -boot start_sasl</input>
-Erlang (BEAM) emulator version 5.4.13 [hipe] [threads:0] [kernel-poll]
+% <input>erl -kernel logger_log_progress true</input>
+Erlang/OTP 21 [erts-10.0] [source-76388a1] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]
-
-=PROGRESS REPORT==== 31-Mar-2006::12:45:58 ===
- supervisor: {local,sasl_safe_sup}
- started: [{pid,&lt;0.33.0>},
- {name,alarm_handler},
- {mfa,{alarm_handler,start_link,[]}},
- {restart_type,permanent},
- {shutdown,2000},
- {child_type,worker}]
-
-=PROGRESS REPORT==== 31-Mar-2006::12:45:58 ===
- supervisor: {local,sasl_safe_sup}
- started: [{pid,&lt;0.34.0>},
- {name,overload},
- {mfa,{overload,start_link,[]}},
- {restart_type,permanent},
- {shutdown,2000},
- {child_type,worker}]
-
-=PROGRESS REPORT==== 31-Mar-2006::12:45:58 ===
- supervisor: {local,sasl_sup}
- started: [{pid,&lt;0.32.0>},
- {name,sasl_safe_sup},
- {mfa,{supervisor,
- start_link,
- [{local,sasl_safe_sup},sasl,safe]}},
- {restart_type,permanent},
- {shutdown,infinity},
- {child_type,supervisor}]
-
-=PROGRESS REPORT==== 31-Mar-2006::12:45:58 ===
- supervisor: {local,sasl_sup}
- started: [{pid,&lt;0.35.0>},
- {name,release_handler},
- {mfa,{release_handler,start_link,[]}},
- {restart_type,permanent},
- {shutdown,2000},
- {child_type,worker}]
-
-=PROGRESS REPORT==== 31-Mar-2006::12:45:58 ===
- application: sasl
- started_at: nonode@nohost
-Eshell V5.4.13 (abort with ^G)
+=PROGRESS REPORT==== 18-May-2018::21:33:41.705292 ===
+ application: kernel
+ started_at: nonode@nohost
+=PROGRESS REPORT==== 18-May-2018::21:33:41.708900 ===
+ application: stdlib
+ started_at: nonode@nohost
+=PROGRESS REPORT==== 18-May-2018::21:33:41.726003 ===
+ supervisor: {local,kernel_safe_sup}
+ started: [{pid,&lt;0.75.0>},
+ {id,disk_log_sup},
+ {mfargs,{disk_log_sup,start_link,[]}},
+ {restart_type,permanent},
+ {shutdown,1000},
+ {child_type,supervisor}]
+=PROGRESS REPORT==== 18-May-2018::21:33:41.726348 ===
+ supervisor: {local,kernel_safe_sup}
+ started: [{pid,&lt;0.76.0>},
+ {id,disk_log_server},
+ {mfargs,{disk_log_server,start_link,[]}},
+ {restart_type,permanent},
+ {shutdown,2000},
+ {child_type,worker}]
+Eshell V9.3.1 (abort with ^G)
1> </pre>
</section>
</chapter>
diff --git a/system/doc/system_principles/system_principles.xml b/system/doc/system_principles/system_principles.xml
index 3605df3ade..b3981f0735 100644
--- a/system/doc/system_principles/system_principles.xml
+++ b/system/doc/system_principles/system_principles.xml
@@ -93,7 +93,7 @@ init:stop()</pre>
{progress,kernel_load_completed}
{progress,modules_loaded}
{start,heart}
-{start,error_logger}
+{start,logger}
...</pre>
<p>For a detailed description of the syntax and contents of the
boot script, see the <c>script(4)</c> manual page in SASL.</p>