diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/kernel/doc/src/error_logger.xml | 233 | ||||
-rw-r--r-- | lib/kernel/doc/src/kernel_app.xml | 8 | ||||
-rw-r--r-- | lib/kernel/doc/src/logger.xml | 44 | ||||
-rw-r--r-- | lib/kernel/doc/src/logger_chapter.xml | 477 | ||||
-rw-r--r-- | lib/kernel/doc/src/logger_formatter.xml | 370 | ||||
-rw-r--r-- | lib/kernel/src/logger.erl | 4 | ||||
-rw-r--r-- | lib/kernel/src/logger_formatter.erl | 21 | ||||
-rw-r--r-- | lib/sasl/doc/src/sasl_app.xml | 4 | ||||
-rw-r--r-- | lib/stdlib/doc/src/proc_lib.xml | 17 |
9 files changed, 708 insertions, 470 deletions
diff --git a/lib/kernel/doc/src/error_logger.xml b/lib/kernel/doc/src/error_logger.xml index e91fc734a4..f418aa5bbe 100644 --- a/lib/kernel/doc/src/error_logger.xml +++ b/lib/kernel/doc/src/error_logger.xml @@ -33,9 +33,10 @@ <description> <note> - <p>In OTP-21, a new API for logging was added to Erlang/OTP. The + <p>In Erlang/OTP 21.0, a new API for logging was added. The old <c>error_logger</c> module can still be used by legacy - code, but new code should use the new API instead.</p> + code, but log events are redirected to the new Logger API. New + code should use the Logger API directly.</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> @@ -89,6 +90,9 @@ The function returns <c>ok</c> if successful.</p> <p>The event handler must be able to handle the events in this module, see section <seealso marker="#events">Events</seealso>.</p> + <p>The first time this function is called, + <c>error_logger</c> is added as a Logger handler, and + the <c>error_logger</c> process is started.</p> </desc> </func> <func> @@ -98,37 +102,40 @@ <p>Deletes an event handler from the error logger by calling <c>gen_event:delete_handler(error_logger, <anno>Handler</anno>, [])</c>, see <seealso marker="stdlib:gen_event"><c>gen_event(3)</c></seealso>.</p> + <p>If no more event handlers exist after the deletion, + <c>error_logger</c> is removed as a Logger handler, and + the <c>error_logger</c> process is stopped.</p> </desc> </func> <func> <name name="error_msg" arity="1"/> <name name="error_msg" arity="2"/> <name name="format" arity="2"/> - <fsummary>Send a standard error event to the error logger.</fsummary> + <fsummary>Log a standard error event.</fsummary> <desc> - <p>Sends a standard error event to the error logger. - The <c><anno>Format</anno></c> and <c><anno>Data</anno></c> arguments - are the same as the arguments of + <p>Log a standard error event. The <c><anno>Format</anno></c> + and <c><anno>Data</anno></c> arguments are the same as the + arguments of <seealso marker="stdlib:io#format/2"><c>io:format/2</c></seealso> - in STDLIB. - The event is handled by the standard event handler.</p> + in STDLIB.</p> + <p>Error logger forwards the event to Logger, including + metadata that allows backwards compatibility with legacy + error logger event handlers.</p> + <p>The event is handled by the default Logger handler.</p> + <p>These functions are kept for backwards compatibility and + must not be used by new code. Use the <seealso marker="logger#macros"> + <c>?LOG_ERROR</c></seealso> macro or + <seealso marker="logger#error-1"><c>logger:error/1,2,3</c></seealso> + instead.</p> <p><em>Example:</em></p> <pre> -1> <input>error_logger:error_msg("An error occurred in ~p~n", [a_module]).</input> - -=ERROR REPORT==== 11-Aug-2005::14:03:19 === +1> <input>error_logger:error_msg("An error occurred in ~p", [a_module]).</input> +=ERROR REPORT==== 22-May-2018::11:18:43.376917 === An error occurred in a_module ok</pre> <warning> - <p>If called with bad arguments, this function can crash - the standard event handler, meaning no further events are - logged. When in doubt, use - <seealso marker="#error_report/1"><c>error_report/1</c></seealso> - instead.</p> - </warning> - <warning> <p>If the Unicode translation modifier (<c>t</c>) is used in - the format string, all error handlers must ensure that the + the format string, all event handlers must ensure that the formatted output is correctly encoded for the I/O device.</p> </warning> @@ -136,36 +143,51 @@ ok</pre> </func> <func> <name name="error_report" arity="1"/> - <fsummary>Send a standard error report event to the error logger.</fsummary> + <fsummary>Log a standard error event.</fsummary> <desc> - <p>Sends a standard error report event to the error logger. - The event is handled by the standard event handler.</p> + <p>Log a standard error event. Error logger forwards the event + to Logger, including metadata that allows backwards + compatibility with legacy error logger event handlers.</p> + <p>The event is handled by the default Logger handler.</p> + <p>This functions is kept for backwards compatibility and + must not be used by new code. Use the <seealso marker="logger#macros"> + <c>?LOG_ERROR</c></seealso> macro or + <seealso marker="logger#error-1"><c>logger:error/1,2,3</c></seealso> + instead.</p> <p><em>Example:</em></p> <pre> 2> <input>error_logger:error_report([{tag1,data1},a_term,{tag2,data}]).</input> - -=ERROR REPORT==== 11-Aug-2005::13:45:41 === +=ERROR REPORT==== 22-May-2018::11:24:23.699306 === tag1: data1 a_term tag2: data ok 3> <input>error_logger:error_report("Serious error in my module").</input> - -=ERROR REPORT==== 11-Aug-2005::13:45:49 === +=ERROR REPORT==== 22-May-2018::11:24:45.972445 === Serious error in my module ok</pre> </desc> </func> <func> <name name="error_report" arity="2"/> - <fsummary>Send a user-defined error report event to the error logger.</fsummary> + <fsummary>Log a user-defined error event.</fsummary> <desc> - <p>Sends a user-defined error report event to the error logger. - An event handler to handle the event is supposed to have been - added. The event is ignored by the standard event handler.</p> + <p>Log a user-defined error event. Error logger forwards the + event to Logger, including metadata that allows backwards + compatibility with legacy error logger event handlers.</p> + <p>Error logger also adds a <c>domain</c> field with + value <c>[<anno>Type</anno>]</c> to this event's metadata, + causing the filters of the default Logger handler to discard + the event. A different Logger handler, or an error logger + event handler, must be added to handle this event.</p> <p>It is recommended that <c><anno>Report</anno></c> follows the same structure as for <seealso marker="#error_report/1"><c>error_report/1</c></seealso>.</p> + <p>This functions is kept for backwards compatibility and + must not be used by new code. Use the <seealso marker="logger#macros"> + <c>?LOG_ERROR</c></seealso> macro or + <seealso marker="logger#error-1"><c>logger:error/1,2,3</c></seealso> + instead.</p> </desc> </func> <func> @@ -181,38 +203,41 @@ 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">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> + the <seealso marker="logger">Logger API</seealso> was + introduced in Erlang/OTP 21.0. The variable, and this + function, are kept for backwards compatibility since they + still might be used by legacy report handlers.</p> </note> </desc> </func> <func> <name name="info_msg" arity="1"/> <name name="info_msg" arity="2"/> - <fsummary>Send a standard information event to the error logger.</fsummary> + <fsummary>Log a standard information event.</fsummary> <desc> - <p>Sends a standard information event to the error logger. - The <c><anno>Format</anno></c> and <c><anno>Data</anno></c> arguments - are the same as the arguments of + <p>Log a standard information event. The <c><anno>Format</anno></c> + and <c><anno>Data</anno></c> arguments are the same as the + arguments of <seealso marker="stdlib:io#format/2"><c>io:format/2</c></seealso> - in STDLIB. The event is handled by the standard event handler.</p> + in STDLIB.</p> + <p>Error logger forwards the event to Logger, including + metadata that allows backwards compatibility with legacy + error logger event handlers.</p> + <p>The event is handled by the default Logger handler.</p> + <p>These functions are kept for backwards compatibility and + must not be used by new code. Use the <seealso marker="logger#macros"> + <c>?LOG_INFO</c></seealso> macro or + <seealso marker="logger#info-1"><c>logger:info/1,2,3</c></seealso> + instead.</p> <p><em>Example:</em></p> <pre> -1> <input>error_logger:info_msg("Something happened in ~p~n", [a_module]).</input> - -=INFO REPORT==== 11-Aug-2005::14:06:15 === +1> <input>error_logger:info_msg("Something happened in ~p", [a_module]).</input> +=INFO REPORT==== 22-May-2018::12:03:32.612462 === Something happened in a_module ok</pre> <warning> - <p>If called with bad arguments, this function can crash - the standard event handler, meaning no further events are - logged. When in doubt, use <c>info_report/1</c> instead.</p> - </warning> - <warning> <p>If the Unicode translation modifier (<c>t</c>) is used in - the format string, all error handlers must ensure that the + the format string, all event handlers must ensure that the formatted output is correctly encoded for the I/O device.</p> </warning> @@ -220,37 +245,52 @@ ok</pre> </func> <func> <name name="info_report" arity="1"/> - <fsummary>Send a standard information report event to the error logger.</fsummary> + <fsummary>Log a standard information event.</fsummary> <desc> - <p>Sends a standard information report event to the error - logger. The event is handled by the standard event handler.</p> + <p>Log a standard information event. Error logger forwards the + event to Logger, including metadata that allows backwards + compatibility with legacy error logger event handlers.</p> + <p>The event is handled by the default Logger handler.</p> + <p>This functions is kept for backwards compatibility and + must not be used by new code. Use the <seealso marker="logger#macros"> + <c>?LOG_INFO</c></seealso> macro or + <seealso marker="logger#info-1"><c>logger:info/1,2,3</c></seealso> + instead.</p> <p><em>Example:</em></p> <pre> 2> <input>error_logger:info_report([{tag1,data1},a_term,{tag2,data}]).</input> - -=INFO REPORT==== 11-Aug-2005::13:55:09 === +=INFO REPORT==== 22-May-2018::12:06:35.994440 === tag1: data1 a_term tag2: data ok 3> <input>error_logger:info_report("Something strange happened").</input> - -=INFO REPORT==== 11-Aug-2005::13:55:36 === +=INFO REPORT==== 22-May-2018::12:06:49.066872 === Something strange happened ok</pre> </desc> </func> <func> <name name="info_report" arity="2"/> - <fsummary>Send a user-defined information report event to the error logger.</fsummary> + <fsummary>Log a user-defined information event.</fsummary> <desc> - <p>Sends a user-defined information report event to the error - logger. An event handler to handle the event is supposed to - have been added. The event is ignored by the standard event - handler.</p> + <p>Log a user-defined information event. Error logger forwards + the event to Logger, including metadata that allows + backwards compatibility with legacy error logger event + handlers.</p> + <p>Error logger also adds a <c>domain</c> field with + value <c>[<anno>Type</anno>]</c> to this event's metadata, + causing the filters of the default Logger handler to discard + the event. A different Logger handler, or an error logger + event handler, must be added to handle this event.</p> <p>It is recommended that <c><anno>Report</anno></c> follows the same structure as for <seealso marker="#info_report/1"><c>info_report/1</c></seealso>.</p> + <p>This functions is kept for backwards compatibility and + must not be used by new code. Use the <seealso marker="logger#macros"> + <c>?LOG_INFO</c></seealso> macro or + <seealso marker="logger#info-1"><c>logger:info/1,2,3</c></seealso> + instead.</p> </desc> </func> <func> @@ -349,24 +389,27 @@ ok</pre> <func> <name name="warning_msg" arity="1"/> <name name="warning_msg" arity="2"/> - <fsummary>Send a standard warning event to the error logger.</fsummary> + <fsummary>Log a standard warning event.</fsummary> <desc> - <p>Sends a standard warning event to the error logger. - The <c><anno>Format</anno></c> and <c><anno>Data</anno></c> arguments - are the same as the arguments of + <p>Log a standard warning event. The <c><anno>Format</anno></c> + and <c><anno>Data</anno></c> arguments are the same as the + arguments of <seealso marker="stdlib:io#format/2"><c>io:format/2</c></seealso> - in STDLIB. - The event is handled by the standard event handler. It is tagged - as an error, warning, or info, see + in STDLIB.</p> + <p>Error logger forwards the event to Logger, including + metadata that allows backwards compatibility with legacy + error logger event handlers.</p> + <p>The event is handled by the default Logger handler. The log + level can be changed to error or info, see <seealso marker="#warning_map/0"><c>warning_map/0</c></seealso>.</p> - <warning> - <p>If called with bad arguments, this function can crash - the standard event handler, meaning no further events are - logged. When in doubt, use <c>warning_report/1</c> instead.</p> - </warning> + <p>These functions are kept for backwards compatibility and + must not be used by new code. Use the <seealso marker="logger#macros"> + <c>?LOG_WARNING</c></seealso> macro or + <seealso marker="logger#warning-1"><c>logger:warning/1,2,3</c></seealso> + instead.</p> <warning> <p>If the Unicode translation modifier (<c>t</c>) is used in - the format string, all error handlers must ensure that the + the format string, all event handlers must ensure that the formatted output is correctly encoded for the I/O device.</p> </warning> @@ -374,24 +417,43 @@ ok</pre> </func> <func> <name name="warning_report" arity="1"/> - <fsummary>Send a standard warning report event to the error logger.</fsummary> + <fsummary>Log a standard warning event.</fsummary> <desc> - <p>Sends a standard warning report event to the error logger. - The event is handled by the standard event handler. It is - tagged as an error, warning, or info, see + <p>Log a standard warning event. Error logger forwards the event + to Logger, including metadata that allows backwards + compatibility with legacy error logger event handlers.</p> + <p>The event is handled by the default Logger handler. The log + level can be changed to error or info, see <seealso marker="#warning_map/0"><c>warning_map/0</c></seealso>.</p> + <p>This functions is kept for backwards compatibility and + must not be used by new code. Use the <seealso marker="logger#macros"> + <c>?LOG_WARNING</c></seealso> macro or + <seealso marker="logger#warning-1"><c>logger:warning/1,2,3</c></seealso> + instead.</p> </desc> </func> <func> <name name="warning_report" arity="2"/> - <fsummary>Send a user-defined warning report event to the error logger.</fsummary> + <fsummary>Log a user-defined warning event.</fsummary> <desc> - <p>Sends a user-defined warning report event to the error - logger. An event handler to handle the event is supposed to - have been added. The event is ignored by the standard event - handler. It is tagged as an error, warning, or info, - depending on the value of + <p>Log a user-defined warning event. Error logger forwards the + event to Logger, including metadata that allows backwards + compatibility with legacy error logger event handlers.</p> + <p>Error logger also adds a <c>domain</c> field with + value <c>[<anno>Type</anno>]</c> to this event's metadata, + causing the filters of the default Logger handler to discard + the event. A different Logger handler, or an error logger + event handler, must be added to handle this event.</p> + <p>The log level can be changed to error or info, see <seealso marker="#warning_map/0"><c>warning_map/0</c></seealso>.</p> + <p>It is recommended that <c><anno>Report</anno></c> follows the same + structure as for + <seealso marker="#warning_report/1"><c>warning_report/1</c></seealso>.</p> + <p>This functions is kept for backwards compatibility and + must not be used by new code. Use the <seealso marker="logger#macros"> + <c>?LOG_WARNING</c></seealso> macro or + <seealso marker="logger#warning-1"><c>logger:warning/1,2,3</c></seealso> + instead.</p> </desc> </func> </funcs> @@ -455,8 +517,9 @@ ok</pre> <section> <title>See Also</title> <p><seealso marker="stdlib:gen_event"><c>gen_event(3)</c></seealso>, - <seealso marker="stdlib:log_mf_h"><c>log_mf_h(3)</c></seealso> - <seealso marker="kernel_app"><c>kernel(6)</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="kernel_app"><c>kernel(6)</c></seealso>, <seealso marker="sasl:sasl_app"><c>sasl(6)</c></seealso></p> </section> </erlref> diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml index 0f7e95472b..e2a6d30249 100644 --- a/lib/kernel/doc/src/kernel_app.xml +++ b/lib/kernel/doc/src/kernel_app.xml @@ -481,13 +481,13 @@ MaxT = TickTime + TickTime / 4</code> <section> <title>Deprecated Configuration Parameters</title> - <p>In OTP-21, a new API for logging was added to Erlang/OTP. The + <p>In Erlang/OTP 21.0, a new API for logging was added. The old <c>error_logger</c> event manager, and event handlers - running on this manager, will still work, but they are not used + running on this manager, still work, but they are no longer used by default.</p> <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> + set, but they are only used if the corresponding configuration + parameters for Logger are not set.</p> <taglist> <tag><c>error_logger</c></tag> <item>Replaced by setting the type of the default diff --git a/lib/kernel/doc/src/logger.xml b/lib/kernel/doc/src/logger.xml index bb356c5b86..c0b3d81367 100644 --- a/lib/kernel/doc/src/logger.xml +++ b/lib/kernel/doc/src/logger.xml @@ -132,6 +132,29 @@ logger:error("error happened because: ~p",[Reason]). %% Without macro log event to the handlers. If the same keys occur, values from the log call overwrite process metadata, which in turn overwrite values set by Logger.</p> + <p>The following custom metadata keys have special meaning:</p> + <taglist> + <tag><c>domain</c></tag> + <item> + <p>The value associated with this key is used by filters + for grouping log events originating from, for example, + specific functional + areas. See <seealso marker="logger_filters#domain-2"> + <c>logger_filters:domain/2</c></seealso> + for a description of how this field can be used.</p> + </item> + <tag><c>report_cb</c></tag> + <item> + <p>If the log message is specified as + a <seealso marker="#type-report"><c>report()</c></seealso>, + the <c>report_cb</c> key can be associated with a fun + (report callback) that converts the report to a format + string and arguments. See + section <seealso marker="logger_chapter#log_message">Log + Message</seealso> in the User's Guide for more + information about report callbacks.</p> + </item> + </taglist> </desc> </datatype> <datatype> @@ -145,7 +168,7 @@ logger:error("error happened because: ~p",[Reason]). %% Without macro <item><c>filters => []</c></item> <item><c>formatter => {logger_formatter,DefaultFormatterConfig</c>}</item> </list> - <p>See the <seealso marker="logger_formatter#configuration"> + <p>See the <seealso marker="logger_formatter#type-config"> <c>logger_formatter(3)</c></seealso> manual page for information about the default configuration for this formatter.</p> @@ -979,6 +1002,25 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(),Meta)). <funcs> <func> + <name>FModule:check_config(FConfig) -> ok | {error,term()}</name> + <fsummary>Validate the given formatter configuration.</fsummary> + <type> + <v>FConfig = + <seealso marker="#type-formatter_config">formatter_config()</seealso></v> + </type> + <desc> + <p>This callback function is optional.</p> + <p>The function is called by a Logger when formatter + configuration is set or modified. The formatter must + validate the given configuration and return <c>ok</c> if it + is correct, and <c>{error,term()}</c> if it is faulty.</p> + <p>See <seealso marker="logger_formatter"> + <c>logger_formatter(3)</c></seealso> + for an example implementation. <c>logger_formatter</c> is the + default formatter used by Logger.</p> + </desc> + </func> + <func> <name>FModule:format(LogEvent,FConfig) -> FormattedLogEntry</name> <fsummary>Format the given log event.</fsummary> <type> diff --git a/lib/kernel/doc/src/logger_chapter.xml b/lib/kernel/doc/src/logger_chapter.xml index 3b4cafb010..a3eec7bd4b 100644 --- a/lib/kernel/doc/src/logger_chapter.xml +++ b/lib/kernel/doc/src/logger_chapter.xml @@ -30,7 +30,7 @@ <file>logger_chapter.xml</file> </header> - <p>As of OTP-21, Erlang/OTP provides a standard API for logging + <p>Erlang/OTP 21.0 provides a new standard API for logging through <c>Logger</c>, which is part of the Kernel application. Logger consists of the API for issuing log events, and a customizable backend where log handlers, filters and @@ -65,63 +65,14 @@ <icaption>Conceptual Overview</icaption> </image> - <marker id="log_levels"/> - <p>In accordance with the Syslog protocol, RFC-5424, eight log - levels can be specified:</p> - - <table align="left"> - <row> - <cell><strong>Level</strong></cell> - <cell align="center"><strong>Integer</strong></cell> - <cell><strong>Description</strong></cell> - </row> - <row> - <cell>emergency</cell> - <cell align="center">0</cell> - <cell>system is unusable</cell> - </row> - <row> - <cell>alert</cell> - <cell align="center">1</cell> - <cell>action must be taken immediately</cell> - </row> - <row> - <cell>critical</cell> - <cell align="center">2</cell> - <cell>critical contidions</cell> - </row> - <row> - <cell>error</cell> - <cell align="center">3</cell> - <cell>error conditions</cell> - </row> - <row> - <cell>warning</cell> - <cell align="center">4</cell> - <cell>warning conditions</cell> - </row> - <row> - <cell>notice</cell> - <cell align="center">5</cell> - <cell>normal but significant conditions</cell> - </row> - <row> - <cell>info</cell> - <cell align="center">6</cell> - <cell>informational messages</cell> - </row> - <row> - <cell>debug</cell> - <cell align="center">7</cell> - <cell>debug-level messages</cell> - </row> - <tcaption>Log Levels</tcaption> - </table> - - <p>A log event passes the level check if the integer value of its - log level is less than or equal to the currently configured log - level, that is, if the event is equally or more severe than the - configured level.</p> + <p>Log levels are expressed as atoms. Internally in Logger, the + atoms are mapped to integer values, and a log event passes the + log level check if the integer value of its log level is less + than or equal to the currently configured log level. That is, + the check pases if the event is equally or more severe than the + configured level. See section <seealso marker="#log_level">Log + Level</seealso> for a listing and description of all log + levels.</p> <p>The global log level can be overridden by a log level configured per module. This is to, for instance, allow more verbose logging from a specific part of the system.</p> @@ -137,14 +88,151 @@ event to its destination. See section <seealso marker="#handlers">Handlers</seealso> for more details.</p> - <p>Everything upto and including the call to the handler callbacks - is executed on the client process, that is, the process where - the log event was issued. It is up to the handler implementation - if other processes are to be involved or not.</p> + <p>Everything up to and including the call to the handler + callbacks is executed on the client process, that is, the + process where the log event was issued. It is up to the handler + implementation if other processes are involved or not.</p> <p>The handlers are called in sequence, and the order is not defined.</p> </section> <section> + <title>Logger API</title> + <p>The API for logging consists of a set + of <seealso marker="logger#macros">macros</seealso>, and a set + of functions on the form <c>logger:Level/1,2,3</c>, which are + all shortcuts + for <seealso marker="logger#log-2"> + <c>logger:log(Level,Arg1[,Arg2[,Arg3]])</c></seealso>.</p> + <p>The difference between using the macros and the exported + functions is that macros add location (originator) information + to the metadata, and performs lazy evaluation by wrapping the + logger call in a case statement, so it is only evaluated if the + log level of the event passes the global log level check.</p> + <section> + <marker id="log_level"/> + <title>Log Level</title> + <p>The log level indicates the severity of a event. In + accordance with the Syslog protocol, RFC-5424, eight log + levels can be specified. The following table lists all + possible log levels by name (atom), integer value, and + description:</p> + + <table align="left"> + <row> + <cell><strong>Level</strong></cell> + <cell align="center"><strong>Integer</strong></cell> + <cell><strong>Description</strong></cell> + </row> + <row> + <cell>emergency</cell> + <cell align="center">0</cell> + <cell>system is unusable</cell> + </row> + <row> + <cell>alert</cell> + <cell align="center">1</cell> + <cell>action must be taken immediately</cell> + </row> + <row> + <cell>critical</cell> + <cell align="center">2</cell> + <cell>critical contidions</cell> + </row> + <row> + <cell>error</cell> + <cell align="center">3</cell> + <cell>error conditions</cell> + </row> + <row> + <cell>warning</cell> + <cell align="center">4</cell> + <cell>warning conditions</cell> + </row> + <row> + <cell>notice</cell> + <cell align="center">5</cell> + <cell>normal but significant conditions</cell> + </row> + <row> + <cell>info</cell> + <cell align="center">6</cell> + <cell>informational messages</cell> + </row> + <row> + <cell>debug</cell> + <cell align="center">7</cell> + <cell>debug-level messages</cell> + </row> + <tcaption>Log Levels</tcaption> + </table> + <p>Notice that the integer value is only used internally in + Logger. In the API, you must always use the atom. To compare + the severity of two log levels, + use <seealso marker="logger#compare_levels-2"> + <c>logger:compare_levels/2</c></seealso>.</p> + </section> + <section> + <marker id="log_message"/> + <title>Log Message</title> + <p>The log message contains the information to be logged. The + message can consist of a format string and arguments (given as + two separate parameters in the Logger API), a string or a + report. The latter, which is either a map or a key-value list, + can be accompanied by a report callback specified in the log + event's <seealso marker="#metadata">metadata</seealso>. The + report callback is a convenience function that + the <seealso marker="#formatters">formatter</seealso> can use + to convert the report to a format string and arguments. The + formatter can also use its own conversion function, if no + callback is provided, or if a customized formatting is + desired.</p> + <p>Example, format string and arguments:</p> + <code>logger:error("The file does not exist: ~ts",[Filename])</code> + <p>Example, string:</p> + <code>logger:notice("Something strange happened!")</code> + <p>Example, report, and metadata with report callback:</p> + <code> +logger:debug(#{got => connection_request, id => Id, state => State}, + #{report_cb => fun(R) -> {"~p",[R]} end})</code> + <p>The log message can also be provided through a fun for lazy + evaluation. The fun is only evaluated if the global log level + check passes, and is therefore recommended if it is expensive + to generate the message. The lazy fun must return a string, a + report, or a tuple with format string and arguments.</p> + </section> + <section> + <title>Metadata</title> + <p>Metadata contains additional data associated with a log + message. Logger inserts some metadata fields by default, and + the client can add custom metadata in two different ways:</p> + <taglist> + <tag>Set process metadata</tag> + <item> + <p>Process metadata is set and updated + with <seealso marker="logger#set_process_metadata-1"> + <c>logger:set_process_metadata/1</c></seealso> + and <seealso marker="logger#update_process_metadata-1"> + <c>logger:update_process metadata/1</c></seealso>, + respectively. This metadata applies to the process on + which these calls are made, and Logger adds the metadata + to all log events issued on that process.</p> + </item> + <tag>Add metadata to a specifc log event</tag> + <item> + <p>Metadata associated with one specifc log event is given + as the last parameter to the log macro or Logger API + function when the event is issued. For example:</p> + <code>?LOG_ERROR("Connection closed",#{context => server})</code> + </item> + </taglist> + <p>See the description of + the <seealso marker="logger#type-metadata"> + <c>logger:metadata()</c></seealso> type for information + about which default keys Logger inserts, and how the different + metadata maps are merged.</p> + </section> + </section> + <section> <marker id="filter"/> <title>Filters</title> <p>Filters can be global, or attached to a specific @@ -166,13 +254,13 @@ discarded. If the filter is global, no handler filters or callbacks are called. If it is a handler filter, the corresponding handler callback is not called, but the log event - is forwarded to the filters attached to the next handler, if + is forwarded to filters attached to the next handler, if any.</p> <p>If the log event is returned, the next filter function is called with the returned value as the first argument. That is, if a filter function modifies the log event, the next filter - function receivea the modified event. The value returned from - the last filter funcion is the value that the handler callback + function receives the modified event. The value returned from + the last filter function is the value that the handler callback receives.</p> <p>If the filter function returns <c>ignore</c>, it means that it did not recognize the log event, and thus leaves to other @@ -180,24 +268,21 @@ <p>The configuration option <seealso marker="#filter_default"><c>filter_default</c></seealso> specifies the behaviour if all filter functions - return <c>ignore</c>. <c>filter_default</c> is by default set - to <c>log</c>, meaning that if all filters ignore a log event, - Logger forwards the event to the handler - callback. If <c>filter_default</c> is set to <c>stop</c>, - Logger discards such events.</p> - - <p>Filters are applied in the reverse order of installation, - meaning that the last added filter is applied first.</p> - + return <c>ignore</c>, or if no filters + exist. <c>filter_default</c> is by default set to <c>log</c>, + meaning that if all existing filters ignore a log event, Logger + forwards the event to the handler + callback. If <c>filter_default</c> is set to <c>stop</c>, Logger + discards such events.</p> <p>Global filters are added with <seealso marker="logger#add_logger_filter-2"> <c>logger:add_logger_filter/2</c></seealso> and removed with <seealso marker="logger#remove_logger_filter-1"> <c>logger:remove_logger_filter/1</c></seealso>. They can also - be added at system start via Kernel configuration + be added at system start via the Kernel configuration parameter <seealso marker="#logger"><c>logger</c></seealso>.</p> - <p>Handler filters are added with + <p>Handler filters are added with <seealso marker="logger#add_handler_filter-3"> <c>logger:add_handler_filter/3</c></seealso> and removed @@ -206,7 +291,7 @@ be specified directly in the configuration when adding a handler with <seealso marker="logger#add_handler/3"> <c>logger:add_handler/3</c></seealso> - or via Kernel configuration + or via the Kernel configuration parameter <seealso marker="#logger"><c>logger</c></seealso>.</p> <p>To see which filters are currently installed in the system, @@ -215,35 +300,37 @@ <c>logger:get_logger_config/0</c></seealso> and <seealso marker="logger#get_handler_config-1"> <c>logger:get_handler_config/1</c></seealso>. Filters are - applied in the order they are listed.</p> + listed in the order they are applied, that is, the first + filter in the list is applied first, and so on.</p> <p>For convenience, the following built-in filters exist:</p> - <list> - <item> - <p><seealso marker="logger_filters#domain-2"> - <c>logger_filters:domain/2</c></seealso> provides a way of - filtering log events based on a - <c>domain</c> field <c>Metadata</c>.</p> - </item> - <item> - <p><seealso marker="logger_filters#level-2"> - <c>logger_filters:level/2</c></seealso> provides a way of - filtering log events based on the log level.</p> - </item> - <item> - <p><seealso marker="logger_filters#progress-2"> - <c>logger_filters:progress/2</c></seealso> stops or allows - progress reports from <c>supervisor</c> - and <c>application_controller</c>.</p> - </item> - <item> - <p><seealso marker="logger_filters#remote_gl-2"> - <c>logger_filters:remote_gl/2</c></seealso> stops or allows - log events originating from a process that has its group - leader on a remote node.</p> - </item> - </list> + <taglist> + <tag><seealso marker="logger_filters#domain-2"> + <c>logger_filters:domain/2</c></seealso></tag> + <item> + <p>Provides a way of filtering log events based on a + <c>domain</c> field in <c>Metadata</c>.</p> + </item> + <tag><seealso marker="logger_filters#level-2"> + <c>logger_filters:level/2</c></seealso></tag> + <item> + <p>Provides a way of filtering log events based on the log + level.</p> + </item> + <tag><seealso marker="logger_filters#progress-2"> + <c>logger_filters:progress/2</c></seealso></tag> + <item> + <p>Stops or allows progress reports from <c>supervisor</c> + and <c>application_controller</c>.</p> + </item> + <tag><seealso marker="logger_filters#remote_gl-2"> + <c>logger_filters:remote_gl/2</c></seealso></tag> + <item> + <p>Stops or allows log events originating from a process + that has its group leader on a remote node.</p> + </item> + </taglist> </section> <section> @@ -252,19 +339,19 @@ <p>A handler is defined as a module exporting at least the following function:</p> - <pre><seealso marker="logger#HModule:log-2">log(LogEvent, Config)</seealso></pre> + <pre><seealso marker="logger#HModule:log-2">log(LogEvent, Config) -> void()</seealso></pre> <p>This function is called when a log event has passed through all global filters, and all handler filters attached to the handler in question. The function call is executed on the client process, and it is up to the handler implementation if other - processes are to be involved or not.</p> + processes are involved or not.</p> <p>Logger allows adding multiple instances of a handler - callback. That is, the callback module might be implemented in - such a way that, by using different handler identities, the same - callback module can be used for multiple handler - instances. Handler configuration is per instance.</p> + callback. That is, if a callback module implementation allows + it, you can add multiple handler instances using the same + callback module. The different instances are identified by + unique handler identities.</p> <p>In addition to the mandatory callback function <c>log/2</c>, a handler module can export the optional callback @@ -281,20 +368,19 @@ <item> <p>This is the default handler used by OTP. Multiple instances can be started, and each instance will write log events to a - given destination, console or file. Filters can be used for - selecting which event to send to which handler instance.</p> + given destination, terminal or file.</p> </item> <tag><c>logger_disk_log_h</c></tag> <item> - <p>This handler behaves much like logger_std_h, except it uses + <p>This handler behaves much like <c>logger_std_h</c>, except it uses <seealso marker="disk_log"><c>disk_log</c></seealso> as its destination.</p> </item> <tag><marker id="ErrorLoggerManager"/><c>error_logger</c></tag> <item> - <p>This handler is to be used for backwards compatibility + <p>This handler is provided for backwards compatibility only. It is not started by default, but will be automatically started the first time an <c>error_logger</c> event handler is added @@ -302,7 +388,8 @@ <c>error_logger:add_report_handler/1,2</c></seealso>.</p> <p>The old <c>error_logger</c> event handlers in STDLIB and - SASL still exist, but they are not added by Erlang/OTP.</p> + SASL still exist, but they are not added by Erlang/OTP 21.0 + or later.</p> </item> </taglist> </section> @@ -312,9 +399,10 @@ <title>Formatters</title> <p>A formatter can be used by the handler implementation to do the final formatting of a log event, before printing to the - handler's destination. The handler callback gets the formatter - information in the handler configuration, which is passed as the - second argument to <seealso marker="logger#HModule:log-2"> + handler's destination. The handler callback receives the + formatter information as part of the handler configuration, + which is passed as the second argument + to <seealso marker="logger#HModule:log-2"> <c>HModule:log/2</c></seealso>.</p> <p>The formatter information consits of a formatter module, <c>FModule</c> and its @@ -322,9 +410,23 @@ following function, which can be called by the handler:</p> <pre><seealso marker="logger#FModule:format-2">format(LogEvent,FConfig) -> FormattedLogEntry</seealso></pre> - <p>See the <seealso marker="logger_formatter"> - <c>logger_formatter(3)</c></seealso> manual for the full - description of the default formatter used by Logger.</p> + <p>The formatter information for a handler is set as a part of its + configuration when the handler is added. It can also be changed + during runtime + with <seealso marker="logger#set_handler_config-3"> + <c>logger:set_handler_config(HandlerId,formatter,{FModule,FConfig})</c> + </seealso>, which overwrites the current formatter information, + or with <seealso marker="logger#update_formatter_config-2"> + <c>logger:update_formatter_config/2,3</c></seealso>, which + only modifies the formatter configuration.</p> + <p>If the formatter module exports the optional callback + function <seealso marker="logger#FModule:check_config-1"> + <c>check_config(FConfig)</c></seealso>, Logger calls this + function when the formatter information is set or modified, to + verify the validity of the formatter configuration.</p> + <p>If no formatter information is specified for a handler, Logger + uses <seealso marker="logger_formatter"> + <c>logger_formatter(3)</c></seealso> as default.</p> </section> <section> @@ -335,7 +437,7 @@ 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 log level.</p> + has to be changed at runtime, such as the log level.</p> <section> <title>Kernel Configuration Parameters</title> @@ -436,9 +538,9 @@ <c>logger:level()</c></seealso></tag> <item> <p>Specifies the global log level to log.</p> - <p>See table <seealso marker="#log_levels">Log - Levels</seealso> in the Overview section for a listing - and description of possible log levels.</p> + <p>See section <seealso marker="#log_level">Log + Level</seealso> for a listing and description of + possible log levels.</p> <p>The initial value of this option is set by the Kernel configuration parameter <seealso marker="kernel_app#logger_level"> @@ -465,7 +567,7 @@ <tag><marker id="filter_default"/><c>filter_default = log | stop</c></tag> <item> <p>Specifies what to do with an event if all filters - return <c>ignore</c>.</p> + return <c>ignore</c>, or if no filters exist.</p> <p>See section <seealso marker="#filters">Filters</seealso> for more information about how this option is used.</p> <p>Default is <c>log</c>.</p> @@ -481,9 +583,9 @@ <c>logger:level()</c></seealso></tag> <item> <p>Specifies the log level which the handler logs.</p> - <p>See table <seealso marker="#log_levels">Log - Levels</seealso> in the Overview section for a listing - and description of possible log levels.</p> + <p>See section <seealso marker="#log_level">Log + Level</seealso> for a listing and description of + possible log levels.</p> <p>The log level can be specified when adding the handler, or changed during runtime with, for instance, <seealso marker="logger#set_handler_config/3"> @@ -509,7 +611,7 @@ <tag><marker id="filter_default"/><c>filter_default = log | stop</c></tag> <item> <p>Specifies what to do with an event if all filters - return <c>ignore</c>.</p> + return <c>ignore</c>, or if no filters exist.</p> <p>See section <seealso marker="#filters">Filters</seealso> for more information about how this option is used.</p> <p>Default is <c>log</c>.</p> @@ -553,14 +655,14 @@ <section> <marker id="compatibility"/> <title>Backwards Compatibility with error_logger</title> - <p>Logger provides backwards compatibility with the old + <p>Logger provides backwards compatibility with <c>error_logger</c> in the following ways:</p> <taglist> <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 + <p>The <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"> @@ -585,7 +687,7 @@ <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>, use the default formatter, <c>logger_formatter</c>, with - configuration parameter <c>legacy_header=>true</c>. This is + configuration parameter <c>legacy_header => true</c>. This is also the default.</p> </item> <tag>Default Format of Log Events from OTP</tag> @@ -608,10 +710,11 @@ 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 behaviour is as follows:</p> + <p>As of Erlang/OTP 21.0, the concept of SASL reports is + removed, meaning that the default behaviour is as + follows:</p> <list> - <item>Supervisor reports, crash reports and progress reports + <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> @@ -626,15 +729,15 @@ 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 + <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</c>.</p> <p>All SASL reports have a metadata - field <c>domain=>[beam,erlang,otp,sasl]</c>, which can be + field <c>domain => [beam,erlang,otp,sasl]</c>, which can be used, for example, by filters to stop or allow the - events.</p> + log 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> @@ -650,14 +753,14 @@ error_logger:add_report_handler/1,2. 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=>[]}. +#{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 + originate from the <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> @@ -676,8 +779,9 @@ error_logger:add_report_handler/1,2. arguments by the handler. If a report is given, a default report callback can be included in the log event's metadata. The handler can use this callback for 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> + format string and arguments. If the format obtained by the + provided callback is not desired, or if there is no provided + callback, the handler must do a custom conversion.</p> <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 @@ -686,18 +790,17 @@ error_logger:add_report_handler/1,2. 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 - 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, - and can be seen if a handler is installed which logs on debug - level.</p> + filter or handler in question from the configuration, and print + a short error message to the terminal. A debug event containing + the crash reason and other details is also issued, and can be + seen if a handler logging debug events is installed.</p> </section> <section> <title>Example: add a handler to log debug events to file</title> - <p>When starting an erlang node, the default behaviour 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 + terminal. 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> @@ -705,28 +808,32 @@ error_logger:add_report_handler/1,2. type <c>{file,File}</c>, and we set the handler's level to <c>debug</c>:</p> <pre> -1> <input>Config = #{level=>debug,logger_std_h=>#{type=>{file,"./debug.log"}}}.</input> +1> <input>Config = #{level => debug, logger_std_h => #{type => {file,"./debug.log"}}}.</input> #{logger_std_h => #{type => {file,"./debug.log"}}, level => debug} 2> <input>logger:add_handler(debug_handler,logger_std_h,Config).</input> ok</pre> <p>By default, the handler receives all events - (<c>filter_defalt=log</c>), so we need to add a filter to stop - all non-debug events:</p> + (<c>filter_default=log</c>, see + section <seealso marker="#filters">Filters</seealso> for more + details), so we need to add a filter to stop all non-debug + events. The built-in + filter <seealso marker="logger_filters#level-2"> + <c>logger_filters:level/2</c></seealso> + is used for this:</p> <pre> -3> <input>Fun = fun(#{level:=debug}=Log,_) -> Log; (_,_) -> stop end.</input> -#Fun<erl_eval.12.98642416> -4> <input>logger:add_handler_filter(debug_handler,allow_debug,{Fun,[]}).</input> +3> <input>logger:add_handler_filter(debug_handler,stop_non_debug, + {fun logger_filters:level/2,{stop,neq,debug}}).</input> ok</pre> <p>And finally, we need to make sure that Logger itself allows debug events. This can either be done by setting the global log level:</p> <pre> -5> <input>logger:set_logger_config(level,debug).</input> +4> <input>logger:set_logger_config(level,debug).</input> ok</pre> <p>Or by allowing debug events from one or a few modules only:</p> <pre> -6> <input>logger:set_module_level(mymodule,debug).</input> +5> <input>logger:set_module_level(mymodule,debug).</input> ok</pre> </section> @@ -736,29 +843,31 @@ ok</pre> <p>The only requirement that a handler MUST fulfill is to export the following function:</p> <code>log(logger:log_event(),logger:config()) -> ok</code> - <p>It may also implement the following callbacks:</p> + <p>It can optionally also implement the following callbacks:</p> <code> adding_handler(logger:config()) -> {ok,logger:config()} | {error,term()} removing_handler(logger:config()) -> ok changing_config(logger:config(),logger:config()) -> {ok,logger:config()} | {error,term()} </code> - <p>When <c>logger:add_handler(Id,Module,Config)</c> is called, Logger - will first call <c>HModule:adding_handler(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 <c>HModule:log/2</c>.</p> + <p>When <c>logger:add_handler(Id,Module,Config)</c> is called, + Logger first calls <c>HModule:adding_handler(Config)</c>. If + this function returns <c>{ok,NewConfig}</c>, Logger + writes <c>NewConfig</c> to the configuration database, and + the <c>logger:add_handler/3</c> call returns. After this, the + handler is installed and must be ready to receive log events as + calls to <c>HModule:log/2</c>.</p> <p>A handler can be removed by calling - <c>logger:remove_handler(Id)</c>. Logger will call - <c>HModule:removing_handler(Config)</c>, and then remove the + <c>logger:remove_handler(Id)</c>. Logger calls + <c>HModule:removing_handler(Config)</c>, and removes 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 + or <c>logger:update_handler_config/2</c> is called, Logger calls <c>HModule:changing_config(OldConfig,NewConfig)</c>. If - this function returns <c>{ok,NewConfig}</c>, <c>NewConfig</c> is - written to the configuration database.</p> + this function returns <c>{ok,NewConfig}</c>, Logger + writes <c>NewConfig</c> to the configuration database.</p> - <p>A simple handler that prints to the console could be - implemented as follows:</p> + <p>A simple handler that prints to the terminal can be implemented + as follows:</p> <code> -module(myhandler). -export([log/2]). @@ -776,7 +885,7 @@ log(LogEvent,#{formatter:={FModule,FConfig}) -> adding_handler(Config) -> {ok,Fd} = file:open(File,[append,{encoding,utf8}]), - {ok,Config#{myhandler_fd=>Fd}}. + {ok,Config#{myhandler_fd => Fd}}. removing_handler(#{myhandler_fd:=Fd}) -> _ = file:close(Fd), @@ -790,10 +899,12 @@ log(LogEvent,#{myhandler_fd:=Fd,formatter:={FModule,FConfig}}) -> protection, and all log events are printed directly from the client process.</p></note> - <p>For examples of overload protection, please refer to the - implementation - of <seealso marker="logger_std_h"><c>logger_std_h</c></seealso> - and <seealso marker="logger_disk_log_h"><c>logger_disk_log_h</c> + <p>For information and examples of overload protection, please + refer to + section <seealso marker="#overload_protection">Protecting the + Handler from Overload</seealso>, and the implementation + of <seealso marker="logger_std_h"><c>logger_std_h(3)</c></seealso> + and <seealso marker="logger_disk_log_h"><c>logger_disk_log_h(3)</c> </seealso>.</p> <p>Below is a simpler example of a handler which logs through one @@ -805,7 +916,7 @@ log(LogEvent,#{myhandler_fd:=Fd,formatter:={FModule,FConfig}}) -> adding_handler(Config) -> {ok,Pid} = gen_server:start(?MODULE,Config), - {ok,Config#{myhandler_pid=>Pid}}. + {ok,Config#{myhandler_pid => Pid}}. removing_handler(#{myhandler_pid:=Pid}) -> gen_server:stop(Pid). @@ -815,7 +926,7 @@ log(LogEvent,#{myhandler_pid:=Pid} = Config) -> init(#{myhandler_file:=File}) -> {ok,Fd} = file:open(File,[append,{encoding,utf8}]), - {ok,#{file=>File,fd=>Fd}}. + {ok,#{file => File, fd => Fd}}. handle_call(_,_,State) -> {reply,{error,bad_request},State}. @@ -949,7 +1060,7 @@ logger:add_handler(my_standard_h, logger_std_h, both built-in handlers offer the possibility to set a maximum level of how many requests to process with a certain time frame. With this burst control feature enabled, the handler will take care of bursts of log requests - without choking log files, or the console, with massive amounts of + without choking log files, or the terminal, with massive amounts of printouts. These are the configuration parameters:</p> <taglist> diff --git a/lib/kernel/doc/src/logger_formatter.xml b/lib/kernel/doc/src/logger_formatter.xml index ee43634cf9..02f89b26be 100644 --- a/lib/kernel/doc/src/logger_formatter.xml +++ b/lib/kernel/doc/src/logger_formatter.xml @@ -46,97 +46,150 @@ Logger.</p> </description> - <section> - <title>Configuration</title> - <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> - <tag><c>chars_limit = pos_integer() | unlimited</c></tag> - <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"><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> - <p>Default is <c>unlimited</c>.</p> - <note> - <p><c>chars_limit</c> has no effect on log messages on - string form. These are expected to be short, but can still - be truncated by the <c>max_size</c> parameter.</p> - </note> - </item> - <tag><marker id="depth"/><c>depth = pos_integer() | unlimited</c></tag> - <item> - <p>A positive integer representing the maximum depth to - which terms shall be printed by this formatter. Format - strings passed to this formatter are rewritten. The format - controls ~p and ~w are replaced with ~P and ~W, - respectively, and the value is used as the depth - parameter. For details, see - <seealso marker="stdlib:io#format-2">io:format/2,3</seealso> - in STDLIB.</p> - <p>Default is <c>unlimited</c>.</p> - <note> - <p><c>depth</c> has no effect on log messages on string - form. These are expected to be short, but can still be - truncated by the <c>max_size</c> parameter.</p> - </note> - </item> - <tag><c>max_size = pos_integer() | unlimited</c></tag> - <item> - <p>A positive integer representing the absolute maximum size a - string returned from this formatter can have. If the - formatted string is longer, after possibly being limited - by <c>chars_limit</c> or <c>depth</c>, it is truncated.</p> - <p>Default is <c>unlimited</c>.</p> - </item> - <tag><c>single_line = boolean()</c></tag> - <item> - <p>If set to <c>true</c>, all newlines in the message are - replaced with <c>", "</c>, and whitespaces following - directly after newlines are removed. Note that newlines - added by the <c>template</c> parameter are not replaced.</p> - <p>Default is <c>true</c>.</p> - </item> - <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 - this field is a string similar to the header created by the - old <c>error_logger</c> event handlers. It can be included - in the log event by adding the - tuple <c>{logger_formatter,header}</c> to the template. See - section <seealso marker="#default_templates">Default - Templates</seealso> for more information.</p> - <p>Default is <c>false</c>.</p> - </item> - <tag><c>report_cb = fun((</c><seealso marker="logger#type-report"><c>logger:report()</c></seealso><c>) -> {</c><seealso marker="stdlib:io#type-format"><c>io:format()</c></seealso><c>,[term()]})</c></tag> - <item> - <p>A report callback is used by the formatter to transform log - messages on report form to a format string and - arguments. The report callback can be specified in the - metadata for the log event. If no report callback exist in - metadata, <c>logger_formatter</c> will - use <seealso marker="logger#format_report-1"> - <c>logger:format_report/1</c></seealso> as default - callback.</p> - <p>If this configuration parameter is set, it replaces both - the default report callback, and any report callback found - in metadata. That is, all reports are converted by this - configured function.</p> - <p>The value must be a function with arity 1, - returning <c>{Format,Args}</c>, and it will be called with a - report as only argument.</p> - </item> - <tag><c>template = </c><seealso marker="#type-template"><c>template()</c></seealso></tag> - <item> + + <datatypes> + <datatype> + <name name="config"/> + <desc> + <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> + <tag><c>chars_limit = pos_integer() | unlimited</c></tag> + <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"> + <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> + <p>Defaults to <c>unlimited</c>.</p> + <note> + <p><c>chars_limit</c> has no effect on log messages on + string form. These are expected to be short, but can + still be truncated by the <c>max_size</c> + parameter.</p> + </note> + </item> + <tag><marker id="depth"/><c>depth = pos_integer() | unlimited</c></tag> + <item> + <p>A positive integer representing the maximum depth to + which terms shall be printed by this formatter. Format + strings passed to this formatter are rewritten. The + format controls ~p and ~w are replaced with ~P and ~W, + respectively, and the value is used as the depth + parameter. For details, see + <seealso marker="stdlib:io#format-2">io:format/2,3</seealso> + in STDLIB.</p> + <p>Defaults to <c>unlimited</c>.</p> + <note> + <p><c>depth</c> has no effect on log messages on string + form. These are expected to be short, but can still be + truncated by the <c>max_size</c> parameter.</p> + </note> + </item> + <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 + this field is a string similar to the header created by + the old <c>error_logger</c> event handlers. It can be + included in the log event by adding the + tuple <c>{logger_formatter,header}</c> to the + template. See the description of + the <seealso marker="#type-template"><c>template()</c></seealso> + type for more information.</p> + <p>Defaults to <c>false</c>.</p> + </item> + <tag><c>max_size = pos_integer() | unlimited</c></tag> + <item> + <p>A positive integer representing the absolute maximum size a + string returned from this formatter can have. If the + formatted string is longer, after possibly being limited + by <c>chars_limit</c> or <c>depth</c>, it is truncated.</p> + <p>Defaults to <c>unlimited</c>.</p> + </item> + <tag><c>report_cb = fun((</c><seealso marker="logger#type-report"><c>logger:report()</c></seealso><c>) -> {</c><seealso marker="stdlib:io#type-format"><c>io:format()</c></seealso><c>,[term()]})</c></tag> + <item> + <p>A report callback is used by the formatter to transform + log messages on report form to a format string and + arguments. The report callback can be specified in the + metadata for the log event. If no report callback exist + in metadata, <c>logger_formatter</c> will + use <seealso marker="logger#format_report-1"> + <c>logger:format_report/1</c></seealso> as default + callback.</p> + <p>If this configuration parameter is set, it replaces + both the default report callback, and any report + callback found in metadata. That is, all reports are + converted by this configured function.</p> + <p>The value must be a function with arity 1, + returning <c>{Format,Args}</c>, and it will be called + with a report as only argument.</p> + </item> + <tag><c>single_line = boolean()</c></tag> + <item> + <p>If set to <c>true</c>, all newlines in the message are + replaced with <c>", "</c>, and whitespaces following + directly after newlines are removed. Note that newlines + added by the <c>template</c> parameter are not replaced.</p> + <p>Defaults to <c>true</c>.</p> + </item> + <tag><c>template = </c><seealso marker="#type-template"><c>template()</c></seealso></tag> + <item> + <p>The template describes how the formatted string is + composed by combining different data values from the log + event. See the description of + the <seealso marker="#type-template"><c>template()</c></seealso> + type for more information about this.</p> + </item> + <tag><c>time_designator = byte()</c></tag> + <item> + <p>Timestamps are formatted according to RFC3339, and the + time designator is the character used as date and time + separator.</p> + <p>Defaults to <c>$T</c>.</p> + <p>The value of this parameter is used as + the <c>time_designator</c> option + to <seealso marker="stdlib:calendar#system_time_to_rfc3339-2"> + <c>calendar:system_time_to_rcf3339/2</c></seealso>.</p> + </item> + <tag><c>time_offset = integer() | [byte()]</c></tag> + <item> + <p>The time offset, either a string or an integer, to be + used when formatting the timestamp.</p> + <p>An empty string is interpreted as local time. The + values <c>"Z"</c>, <c>"z"</c> or <c>0</c> are + interpreted as Universal Coordinated Time (UTC).</p> + <p>Strings, other than <c>"Z"</c>, <c>"z"</c>, + or <c>""</c>, must be on the form <c>±[hh]:[mm]</c>, for + example <c>"-02:00"</c> or <c>"+00:00"</c>.</p> + <p>Integers must be in microseconds, meaning that the + offset <c>7200000000</c> is equivalent + to <c>"+02:00"</c>.</p> + <p>Defaults to an empty string, meaning that timestamps + are displayed in local time. However, for 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> + <p>The value of this parameter is used as + the <c>offset</c> option + to <seealso marker="stdlib:calendar#system_time_to_rfc3339-2"> + <c>calendar:system_time_to_rcf3339/2</c></seealso>.</p> + </item> + </taglist> + </desc> + </datatype> + <datatype> + <name name="template"/> + <desc> <p>The template is a list of atoms, tuples and strings. The atoms <c>level</c> or <c>msg</c>, are treated as placeholders for the severity level and the log message, - repectively. Other atoms or tuples are interpreted as + respectively. Other atoms or tuples are interpreted as placeholders for metadata, where atoms are expected to match top level keys, and tuples represent paths to sub keys when the metadata is a nested map. For example the @@ -154,121 +207,85 @@ <p>Strings in the template are printed literally.</p> <p>The default template differs depending on the values of <c>legacy_header</c> - and <c>single_line</c>. See <seealso marker="#default_templates">Default - Templates</seealso> for more information</p> - </item> - <tag><c>time_designator = byte()</c></tag> - <item> - <p>Timestamps are formatted according to RFC3339, and the time - designator is the character used as date and time - separator.</p> - <p>Default is <c>$T</c>.</p> - <p>The value of this parameter is used as - the <c>time_designator</c> option - to <seealso marker="stdlib:calendar#system_time_to_rfc3339-2"> - <c>calendar:system_time_to_rcf3339/2</c></seealso>.</p> - </item> - <tag><c>time_offset = integer() | [byte()]</c></tag> - <item> - <p>The time offset, either a string or an integer, to be - used when formatting the timestamp.</p> - <p>An empty string is interpreted as local time. The - values <c>"Z"</c>, <c>"z"</c> or <c>0</c> are interpreted as - Universal Coordinated Time (UTC).</p> - <p>Strings, other than <c>"Z"</c>, <c>"z"</c>, or <c>""</c>, - must be on the form <c>±[hh]:[mm]</c>, for - example <c>"-02:00"</c> or <c>"+00:00"</c>.</p> - <p>Integers must be in microseconds, meaning that the - offset <c>7200000000</c> is equivalent - 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 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> - <p>The value of this parameter is used as the <c>offset</c> - option to <seealso marker="stdlib:calendar#system_time_to_rfc3339-2"> - <c>calendar:system_time_to_rcf3339/2</c></seealso>.</p> - </item> - </taglist> - </section> - - <section> - <marker id="default_templates"/> - <title>Default templates</title> + and <c>single_line</c>:</p> - <p>The default value for the <c>template</c> configuration - parameter depends on the value of <c>single_line</c> - and <c>legacy_header</c> as follows.</p> + <p>The default value for the <c>template</c> configuration + parameter depends on the value of the <c>single_line</c> + and <c>legacy_header</c> configuration parameters as + follows.</p> - <p>The log event used in the examples is:</p> - <code> + <p>The log event used in the examples is:</p> + <code> ?LOG_ERROR("name: ~p~nexit_reason: ~p",[my_name,"It crashed"])</code> - <taglist> - <tag><c>legacy_header=true, single_line=false</c></tag> - <item> - <p>Default template: <c>[{logger_formatter,header},"\n",msg,"\n"]</c></p> + <taglist> + <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"> + <p>Example log entry:</p> + <code type="none"> =ERROR REPORT==== 17-May-2018::18:30:19.453447 === name: my_name exit_reason: "It crashed"</code> - <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> + <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>legacy_header=true, single_line=true</c></tag> - <item> - <p>Default template: <c>[{logger_formatter,header},"\n",msg,"\n"]</c></p> + <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"> + <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> + </item> - <tag><c>legacy_header=false, single_line=true</c></tag> - <item> - <p>Default template: <c>[time," ",level,": ",msg,"\n"]</c></p> + <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"> + <p>Example log entry:</p> + <code type="none"> 2018-05-17T18:31:31.152864+02:00 error: name: my_name, exit_reason: "It crashed"</code> - </item> + </item> - <tag><c>legacy_header=false, single_line=false</c></tag> - <item> - <p>Default template: <c>[time," ",level,":\n",msg,"\n"]</c></p> + <tag><c>legacy_header=false, single_line=false</c></tag> + <item> + <p>Default template: <c>[time," ",level,":\n",msg,"\n"]</c></p> - <p>Example log entry:</p> - <code type="none"> + <p>Example log entry:</p> + <code type="none"> 2018-05-17T18:32:20.105422+02:00 error: name: my_name exit_reason: "It crashed"</code> - </item> - </taglist> - </section> - - <datatypes> - <datatype> - <name name="template"/> - <desc> + </item> + </taglist> </desc> </datatype> </datatypes> <funcs> <func> + <name name="check_config" arity="1"/> + <fsummary>Validates the given formatter configuration.</fsummary> + <desc> + <p>This callback function is called by Logger when the + formatter configuration for a handler is set or modified. It + returns <c>ok</c> if the configuration is valid, + and <c>{error,term()}</c> if it is faulty.</p> + </desc> + </func> + <func> <name name="format" arity="2"/> <fsummary>Formats the given message.</fsummary> <desc> @@ -290,7 +307,6 @@ exit_reason: "It crashed"</code> </list> </desc> </func> - </funcs> </erlref> diff --git a/lib/kernel/src/logger.erl b/lib/kernel/src/logger.erl index 12f8dd77cf..3beb3102fa 100644 --- a/lib/kernel/src/logger.erl +++ b/lib/kernel/src/logger.erl @@ -81,7 +81,9 @@ mfa => {module(),atom(),non_neg_integer()}, file => file:filename(), line => non_neg_integer(), - term() => term()}. + domain => [atom()], + report_cb => fun((report()) -> {io:format(),[term()]}), + atom() => term()}. -type location() :: #{mfa := {module(),atom(),non_neg_integer()}, file := file:filename(), line := non_neg_integer()}. diff --git a/lib/kernel/src/logger_formatter.erl b/lib/kernel/src/logger_formatter.erl index 95cb6e35fc..4d727b3da0 100644 --- a/lib/kernel/src/logger_formatter.erl +++ b/lib/kernel/src/logger_formatter.erl @@ -26,21 +26,22 @@ %%%----------------------------------------------------------------- %%% Types +-type config() :: #{chars_limit=>pos_integer()| unlimited, + depth=>pos_integer() | unlimited, + legacy_header=>boolean(), + max_size=>pos_integer() | unlimited, + report_cb=>fun((logger:report()) -> {io:format(),[term()]}), + single_line=>boolean(), + template=>template(), + time_designator=>byte(), + time_offset=>integer()|[byte()]}. -type template() :: [atom()|tuple()|string()]. %%%----------------------------------------------------------------- %%% API -spec format(LogEvent,Config) -> unicode:chardata() when LogEvent :: logger:log_event(), - Config :: #{single_line=>boolean(), - legacy_header=>boolean(), - report_cb=>fun((logger:report()) -> {io:format(),[term()]}), - chars_limit=>pos_integer()| unlimited, - max_size=>pos_integer() | unlimited, - depth=>pos_integer() | unlimited, - template=>template(), - time_designator=>byte(), - time_offset=>integer()|[byte()]}. + Config :: config(). format(#{level:=Level,msg:=Msg0,meta:=Meta},Config0) when is_map(Config0) -> Config = add_default_config(Config0), @@ -322,6 +323,8 @@ offset_to_utc([$+|Tz]) -> offset_to_utc(_) -> false. +-spec check_config(Config) -> ok | {error,term()} when + Config :: config(). check_config(Config) when is_map(Config) -> do_check_config(maps:to_list(Config)); check_config(Config) -> diff --git a/lib/sasl/doc/src/sasl_app.xml b/lib/sasl/doc/src/sasl_app.xml index 7f4ceeb354..be275879ee 100644 --- a/lib/sasl/doc/src/sasl_app.xml +++ b/lib/sasl/doc/src/sasl_app.xml @@ -92,9 +92,9 @@ <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 + <p>In Erlang/OTP 21.0, a new API for logging was added. The old <c>error_logger</c> event manager, and event handlers - running on this manager, will still work, but they are not used + running on this manager, 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 earlier used for printing diff --git a/lib/stdlib/doc/src/proc_lib.xml b/lib/stdlib/doc/src/proc_lib.xml index c4fdf972e4..51380ae51c 100644 --- a/lib/stdlib/doc/src/proc_lib.xml +++ b/lib/stdlib/doc/src/proc_lib.xml @@ -61,8 +61,9 @@ <c>shutdown</c>, or <c>{shutdown,Term}</c>), a <em>crash report</em> 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> + were logged prior to Erlang/OTP 21.0, 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 @@ -118,9 +119,9 @@ 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 + API</seealso> was added in Erlang/OTP 21.0, but + legacy <c>error_logger</c> handlers can still be used. New + Logger handlers do not need to use this function, since the formatting callback (<c>report_cb</c>) is included as metadata in the log event.</p> </note> @@ -145,9 +146,9 @@ 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 + API</seealso> was added in Erlang/OTP 21.0, but + legacy <c>error_logger</c> handlers can 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> |