aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel/doc/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kernel/doc/src')
-rw-r--r--lib/kernel/doc/src/.gitignore1
-rw-r--r--lib/kernel/doc/src/Makefile48
-rw-r--r--lib/kernel/doc/src/application.xml12
-rw-r--r--lib/kernel/doc/src/book.xml5
-rw-r--r--lib/kernel/doc/src/code.xml20
-rw-r--r--lib/kernel/doc/src/config.xml15
-rw-r--r--lib/kernel/doc/src/erl_epmd.xml104
-rw-r--r--lib/kernel/doc/src/error_logger.xml325
-rw-r--r--lib/kernel/doc/src/file.xml277
-rw-r--r--lib/kernel/doc/src/heart.xml7
-rw-r--r--lib/kernel/doc/src/inet.xml81
-rw-r--r--lib/kernel/doc/src/inet_res.xml8
-rw-r--r--lib/kernel/doc/src/introduction_chapter.xml63
-rw-r--r--lib/kernel/doc/src/kernel_app.xml228
-rw-r--r--lib/kernel/doc/src/logger.xml1169
-rw-r--r--lib/kernel/doc/src/logger_arch.diabin0 -> 2527 bytes
-rw-r--r--lib/kernel/doc/src/logger_arch.pngbin0 -> 117205 bytes
-rw-r--r--lib/kernel/doc/src/logger_chapter.xml1331
-rw-r--r--lib/kernel/doc/src/logger_disk_log_h.xml158
-rw-r--r--lib/kernel/doc/src/logger_filters.xml254
-rw-r--r--lib/kernel/doc/src/logger_formatter.xml355
-rw-r--r--lib/kernel/doc/src/logger_std_h.xml130
-rw-r--r--lib/kernel/doc/src/net_kernel.xml15
-rw-r--r--lib/kernel/doc/src/notes.xml285
-rw-r--r--lib/kernel/doc/src/os.xml92
-rw-r--r--lib/kernel/doc/src/part.xml37
-rw-r--r--lib/kernel/doc/src/ref_man.xml12
-rw-r--r--lib/kernel/doc/src/rpc.xml11
-rw-r--r--lib/kernel/doc/src/seq_trace.xml11
-rw-r--r--lib/kernel/doc/src/specs.xml6
30 files changed, 4621 insertions, 439 deletions
diff --git a/lib/kernel/doc/src/.gitignore b/lib/kernel/doc/src/.gitignore
new file mode 100644
index 0000000000..c2813ac866
--- /dev/null
+++ b/lib/kernel/doc/src/.gitignore
@@ -0,0 +1 @@
+*.eps \ No newline at end of file
diff --git a/lib/kernel/doc/src/Makefile b/lib/kernel/doc/src/Makefile
index 0759f362d4..f8867ccf25 100644
--- a/lib/kernel/doc/src/Makefile
+++ b/lib/kernel/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 1997-2016. All Rights Reserved.
+# Copyright Ericsson AB 1997-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -42,6 +42,7 @@ XML_REF3_FILES = application.xml \
disk_log.xml \
erl_boot_server.xml \
erl_ddll.xml \
+ erl_epmd.xml \
erl_prim_loader_stub.xml \
erlang_stub.xml \
error_handler.xml \
@@ -56,6 +57,11 @@ XML_REF3_FILES = application.xml \
inet.xml \
inet_res.xml \
init_stub.xml \
+ logger.xml \
+ logger_std_h.xml \
+ logger_disk_log_h.xml \
+ logger_filters.xml \
+ logger_formatter.xml \
net_adm.xml \
net_kernel.xml \
os.xml \
@@ -70,11 +76,18 @@ XML_REF4_FILES = app.xml config.xml
XML_REF6_FILES = kernel_app.xml
-XML_PART_FILES =
-XML_CHAPTER_FILES = notes.xml
+XML_PART_FILES = part.xml
+XML_CHAPTER_FILES = \
+ notes.xml \
+ introduction_chapter.xml \
+ logger_chapter.xml
BOOK_FILES = book.xml
+# The .png file is generated from a .dia file with target 'update_png'
+IMAGE_FILES = \
+ logger_arch.png
+
XML_FILES = \
$(BOOK_FILES) $(XML_CHAPTER_FILES) \
$(XML_PART_FILES) $(XML_REF3_FILES) $(XML_REF4_FILES)\
@@ -100,6 +113,17 @@ SPECS_FILES = $(XML_REF3_FILES:%.xml=$(SPECDIR)/specs_%.xml)
TOP_SPECS_FILE = specs.xml
# ----------------------------------------------------
+# FIGURES
+# ----------------------------------------------------
+# In order to update the figures you have to have both dia
+# and imagemagick installed.
+# The generated .png file must be committed.
+
+update_png:
+ dia --export=logger_arch.eps logger_arch.dia
+ convert logger_arch.eps -resize 65% logger_arch.png
+
+# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
XML_FLAGS +=
@@ -111,7 +135,7 @@ SPECS_FLAGS = -I../../include
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
-$(HTMLDIR)/%.gif: %.gif
+$(HTMLDIR)/%: %
$(INSTALL_DATA) $< $@
docs: man pdf html
@@ -120,33 +144,35 @@ $(TOP_PDF_FILE): $(XML_FILES)
pdf: $(TOP_PDF_FILE)
-html: gifs $(HTML_REF_MAN_FILE)
+html: images $(HTML_REF_MAN_FILE)
man: $(MAN3_FILES) $(MAN4_FILES) $(MAN6_FILES)
-gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
+images: $(IMAGE_FILES:%=$(HTMLDIR)/%)
+
debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(MAN4DIR)/*
rm -f $(MAN6DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
rm -f $(SPECDIR)/*
- rm -f errs core *~
+ rm -f errs core *~ *.eps
$(SPECDIR)/specs_erl_prim_loader_stub.xml:
- escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
+ $(gen_verbose)escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
-o$(dir $@) -module erl_prim_loader_stub
$(SPECDIR)/specs_erlang_stub.xml:
- escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
+ $(gen_verbose)escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
-o$(dir $@) -module erlang_stub
$(SPECDIR)/specs_init_stub.xml:
- escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
+ $(gen_verbose)escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
-o$(dir $@) -module init_stub
$(SPECDIR)/specs_zlib_stub.xml:
- escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
+ $(gen_verbose)escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
-o$(dir $@) -module zlib_stub
# ----------------------------------------------------
diff --git a/lib/kernel/doc/src/application.xml b/lib/kernel/doc/src/application.xml
index 886286b76d..38c7b5acf1 100644
--- a/lib/kernel/doc/src/application.xml
+++ b/lib/kernel/doc/src/application.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -318,8 +318,13 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
<c>{error,{not_started,App}}</c> is returned, where <c>App</c>
is the name of the missing application.</p>
<p>The application controller then creates an <em>application master</em>
- for the application. The application master is
- the group leader of all the processes in the application.
+ for the application. The application master becomes the
+ group leader of all the processes in the application. I/O is
+ forwarded to the previous group leader, though, this is just
+ a way to identify processes that belong to the application.
+ Used for example to find itself from any process, or,
+ reciprocally, to kill them all when it terminates.</p>
+ <p>
The application master starts the application by calling
the application callback function <c>Module:start/2</c> as
defined by the application specification key <c>mod</c>.</p>
@@ -608,4 +613,3 @@ Nodes = [cp1@cave, {cp2@cave, cp3@cave}]</code>
<seealso marker="app">app(4)</seealso></p>
</section>
</erlref>
-
diff --git a/lib/kernel/doc/src/book.xml b/lib/kernel/doc/src/book.xml
index 81a87d126d..4b3573b9fe 100644
--- a/lib/kernel/doc/src/book.xml
+++ b/lib/kernel/doc/src/book.xml
@@ -4,7 +4,7 @@
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<header titlestyle="normal">
<copyright>
- <year>1997</year><year>2016</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -34,6 +34,9 @@
<preamble>
<contents level="2"></contents>
</preamble>
+ <parts lift="yes">
+ <xi:include href="part.xml"/>
+ </parts>
<applications>
<xi:include href="ref_man.xml"/>
</applications>
diff --git a/lib/kernel/doc/src/code.xml b/lib/kernel/doc/src/code.xml
index c94f612c01..aff3e8133c 100644
--- a/lib/kernel/doc/src/code.xml
+++ b/lib/kernel/doc/src/code.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2017</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -34,26 +34,28 @@
<p>This module contains the interface to the Erlang
<em>code server</em>, which deals with the loading of compiled
code into a running Erlang runtime system.</p>
- <p>The runtime system can be started in <em>embedded</em> or
- <em>interactive</em> mode. Which one is decided by command-line
+ <p>The runtime system can be started in <em>interactive</em> or
+ <em>embedded</em> mode. Which one is decided by the command-line
flag <c>-mode</c>:</p>
<pre>
% <input>erl -mode interactive</input></pre>
<p>The modes are as follows:</p>
<list type="bulleted">
<item>
- <p>In embedded mode, all code is loaded during system startup
- according to the boot script. (Code can also be loaded later
- by explicitly ordering the code server to do so).</p>
- </item>
- <item>
<p>In interactive mode, which is default, only some code is loaded
- during system startup, basically the modules needed by the runtime
+ during system startup, basically the modules needed by the runtime
system. Other code is dynamically loaded when first
referenced. When a call to a function in a certain module is
made, and the module is not loaded, the code server searches
for and tries to load the module.</p>
</item>
+ <item>
+ <p>In embedded mode, modules are not auto loaded. Trying to use
+ a module that has not been loaded results in an error. This mode is
+ recommended when the boot script loads all modules, as it is
+ typically done in OTP releases. (Code can still be loaded later
+ by explicitly ordering the code server to do so).</p>
+ </item>
</list>
<p>To prevent accidentally reloading of modules affecting the Erlang
runtime system, directories <c>kernel</c>, <c>stdlib</c>,
diff --git a/lib/kernel/doc/src/config.xml b/lib/kernel/doc/src/config.xml
index fdb2d29f63..714af93f4d 100644
--- a/lib/kernel/doc/src/config.xml
+++ b/lib/kernel/doc/src/config.xml
@@ -4,7 +4,7 @@
<fileref>
<header>
<copyright>
- <year>1997</year><year>2017</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -37,10 +37,10 @@
data in the system configuration file <c>Name.config</c>.</p>
<p>Configuration parameter values in the configuration file
override the values in the application resource files (see
- <seealso marker="app"><c>app(4)</c></seealso>.
+ <seealso marker="app"><c>app(4)</c></seealso>).
The values in the configuration file can be
overridden by command-line flags (see
- <seealso marker="erts:erl"><c>erts:erl(1)</c></seealso>.</p>
+ <seealso marker="erts:erl"><c>erts:erl(1)</c></seealso>).</p>
<p>The value of a configuration parameter is retrieved by calling
<c>application:get_env/1,2</c>.</p>
</description>
@@ -86,8 +86,13 @@
<tag><c>File = string()</c></tag>
<item>Name of another <c>.config</c> file.
Extension <c>.config</c> can be omitted. It is
- recommended to use absolute paths. A relative path is
- relative the current working directory of the emulator.</item>
+ recommended to use absolute paths. If a relative path is used,
+ <c>File</c> is searched, first, relative from <c>sys.config</c> directory, then relative
+ to the current working directory of the emulator, for backward compatibility.
+ This allow to use a <c>sys.config</c> pointing out other <c>.config</c> files in a release
+ or in a node started manually using <c>-config ...</c> with same result whatever
+ the current working directory.
+ </item>
</taglist>
<p>When traversing the contents of <c>sys.config</c> and a filename
is encountered, its contents are read and merged with the result
diff --git a/lib/kernel/doc/src/erl_epmd.xml b/lib/kernel/doc/src/erl_epmd.xml
new file mode 100644
index 0000000000..8b076cd2d7
--- /dev/null
+++ b/lib/kernel/doc/src/erl_epmd.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2018</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>erl_epmd</title>
+ <prepared>Timmo Verlaan</prepared>
+ <docno>1</docno>
+ <date>2018-02-19</date>
+ <rev>A</rev>
+ </header>
+ <module>erl_epmd</module>
+ <modulesummary>
+ Erlang interface towards epmd
+ </modulesummary>
+ <description>
+ <p>This module communicates with the EPMD daemon, see <seealso
+ marker="erts:epmd">epmd</seealso>. To implement your own epmd module please
+ see <seealso marker="erts:alt_disco">ERTS User's Guide: How to Implement an
+ Alternative Service Discovery for Erlang Distribution</seealso></p>
+ </description>
+
+ <funcs>
+ <func>
+ <name name="start_link" arity="0"/>
+ <fsummary>Callback for erl_distribution supervisor.</fsummary>
+ <desc>
+ <p>This function is invoked as this module is added as a child of the
+ <c>erl_distribution</c> supervisor.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="register_node" arity="2"/>
+ <name name="register_node" arity="3"/>
+ <fsummary>Registers the node with <c>epmd</c>.</fsummary>
+ <desc>
+ <p>Registers the node with <c>epmd</c> and tells epmd what port will be
+ used for the current node. It returns a creation number. This number is
+ incremented on each register to help with identifying if a node is
+ reconnecting to epmd.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="port_please" arity="2"/>
+ <name name="port_please" arity="3"/>
+ <fsummary>Returns the port number for a given node.</fsummary>
+ <desc>
+ <p>Requests the distribution port for the given node of an EPMD
+ instance. Together with the port it returns a distribution protocol
+ version which has been 5 since Erlang/OTP R6.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="address_please" arity="3"/>
+ <fsummary>Returns address and port.</fsummary>
+ <desc>
+ <p>Called by the distribution module. Resolves the <c>Host</c> to an IP
+ address.</p>
+ <p>Another epmd module may return port and distribution protocol version
+ as well.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="names" arity="1"/>
+ <fsummary>Names of Erlang nodes at a host.</fsummary>
+ <desc>
+ <p>Called by <seealso marker="net_adm"><c>net_adm:names/0</c></seealso>.
+ <c>Host</c> defaults to the localhost. Returns the names and associated
+ port numbers of the Erlang nodes that <c>epmd</c> registered at the
+ specified host. Returns <c>{error, address}</c> if <c>epmd</c> is not
+ operational.</p>
+ <p><em>Example:</em></p>
+ <pre>
+(arne@dunn)1> <input>erl_epmd:names(localhost).</input>
+{ok,[{"arne",40262}]}</pre>
+ </desc>
+ </func>
+ </funcs>
+
+</erlref>
+
diff --git a/lib/kernel/doc/src/error_logger.xml b/lib/kernel/doc/src/error_logger.xml
index 91bf57cb91..c3d68fd79f 100644
--- a/lib/kernel/doc/src/error_logger.xml
+++ b/lib/kernel/doc/src/error_logger.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2017</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,36 +31,37 @@
<module>error_logger</module>
<modulesummary>Erlang error logger.</modulesummary>
<description>
+
+ <note>
+ <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 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>
+ 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>
+ </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
@@ -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>
@@ -174,38 +196,48 @@ ok</pre>
<c>error_logger_format_depth</c>.</fsummary>
<desc>
<p>Returns <c>max(10, Depth)</c>, where <c>Depth</c> is the
- value of
- <seealso marker="kernel:kernel_app#error_logger_format_depth">
- error_logger_format_depth</seealso>
+ value of <c>error_logger_format_depth</c>
in the Kernel application, if Depth is an integer. Otherwise,
<c>unlimited</c> is returned.</p>
+ <note>
+ <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
+ 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>
@@ -213,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>
@@ -258,14 +305,22 @@ ok</pre>
<type name="open_error"/>
<desc>
<p>Enables or disables printout of standard events to a file.</p>
- <p>This is done by adding or deleting the standard event handler
- for output to file. Thus, calling this function overrides
- the value of the Kernel <c>error_logger</c> configuration
- parameter.</p>
- <p>Enabling file logging can be used together with calling
- <c>tty(false)</c>, to have a silent system where
- all standard events are logged to a file only.
- Only one log file can be active at a time.</p>
+ <p>This is done by adding or deleting
+ the <c>error_logger_file_h</c> event handler, and thus
+ indirectly adding <c>error_logger</c> as a Logger
+ handler.</p>
+ <p>Notice that this function does not manipulate the Logger
+ configuration directly, meaning that if the default Logger
+ handler is already logging to a file, this function can
+ potentially cause logging to a second file.</p>
+ <p>This function is useful as a shortcut during development
+ and testing, but must not be used in a production
+ system. See
+ section <seealso marker="logger_chapter">Logging</seealso>
+ in the Kernel User's Guide, and
+ the <seealso marker="logger"><c>logger(3)</c></seealso>
+ manual page for information about how to configure Logger
+ for live systems.</p>
<p><c>Request</c> is one of the following:</p>
<taglist>
<tag><c>{open, <anno>Filename</anno>}</c></tag>
@@ -297,9 +352,14 @@ ok</pre>
<p>Enables (<c><anno>Flag</anno> == true</c>) or disables
(<c><anno>Flag</anno> == false</c>) printout of standard events
to the terminal.</p>
- <p>This is done by adding or deleting the standard event handler
- for output to the terminal. Thus, calling this function overrides
- the value of the Kernel <c>error_logger</c> configuration parameter.</p>
+ <p>This is done by manipulating the Logger configuration. The
+ function is useful as a shortcut during development and
+ testing, but must not be used in a production system. See
+ section <seealso marker="logger_chapter">Logging</seealso>
+ in the Kernel User's Guide, and
+ the <seealso marker="logger"><c>logger(3)</c></seealso>
+ manual page for information about how to configure Logger
+ for live systems.</p>
</desc>
</func>
<func>
@@ -342,24 +402,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>
@@ -367,24 +430,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>
@@ -448,8 +530,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/file.xml b/lib/kernel/doc/src/file.xml
index b674b3ca93..9acaf6b41e 100644
--- a/lib/kernel/doc/src/file.xml
+++ b/lib/kernel/doc/src/file.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -33,15 +33,18 @@
<description>
<p>This module provides an interface to the file system.</p>
- <p>On operating systems with thread support,
- file operations can be performed in threads of their own, allowing
- other Erlang processes to continue executing in parallel with
- the file operations. See command-line flag
- <c>+A</c> in <seealso marker="erts:erl"><c>erl(1)</c></seealso>.</p>
+ <warning>
+ <p>File operations are only guaranteed to appear atomic when going
+ through the same file server. A NIF or other OS process may observe
+ intermediate steps on certain operations on some operating systems,
+ eg. renaming an existing file on Windows, or
+ <seealso marker="#write_file_info/2"><c>write_file_info/2</c>
+ </seealso> on any OS at the time of writing.</p>
+ </warning>
<p>Regarding filename encoding, the Erlang VM can operate in
two modes. The current mode can be queried using function
- <seealso marker="#native_name_encoding"><c>native_name_encoding/0</c></seealso>.
+ <seealso marker="#native_name_encoding/0"><c>native_name_encoding/0</c></seealso>.
It returns <c>latin1</c> or <c>utf8</c>.</p>
<p>In <c>latin1</c> mode, the Erlang VM does not change the
@@ -59,7 +62,7 @@
terminal supports UTF-8, otherwise <c>latin1</c>. The default can
be overridden using <c>+fnl</c> (to force <c>latin1</c> mode)
or <c>+fnu</c> (to force <c>utf8</c> mode) when starting
- <seealso marker="erts:erl"><c>erts:erl</c></seealso>.</p>
+ <seealso marker="erts:erl"><c>erl</c></seealso>.</p>
<p>On operating systems with transparent naming, files can be
inconsistently named, for example, some files are encoded in UTF-8 while
@@ -81,6 +84,16 @@
<p>See also section <seealso marker="stdlib:unicode_usage#notes-about-raw-filenames">Notes About Raw Filenames</seealso> in the STDLIB User's Guide.</p>
+ <note><p>
+ File operations used to accept filenames containing
+ null characters (integer value zero). This caused
+ the name to be truncated and in some cases arguments
+ to primitive operations to be mixed up. Filenames
+ containing null characters inside the filename
+ are now <em>rejected</em> and will cause primitive
+ file operations fail.
+ </p></note>
+
</description>
<datatypes>
@@ -96,9 +109,21 @@
</datatype>
<datatype>
<name name="filename"/>
+ <desc>
+ <p>
+ See also the documentation of the
+ <seealso marker="#type-name_all"><c>name_all()</c></seealso> type.
+ </p>
+ </desc>
</datatype>
<datatype>
<name name="filename_all"/>
+ <desc>
+ <p>
+ See also the documentation of the
+ <seealso marker="#type-name_all"><c>name_all()</c></seealso> type.
+ </p>
+ </desc>
</datatype>
<datatype>
<name name="io_device"/>
@@ -112,21 +137,23 @@
<name name="name"/>
<desc>
<p>If VM is in Unicode filename mode, <c>string()</c> and <c>char()</c>
- are allowed to be &gt; 255.
+ are allowed to be &gt; 255. See also the documentation of the
+ <seealso marker="#type-name_all"><c>name_all()</c></seealso> type.
</p>
</desc>
</datatype>
<datatype>
<name name="name_all"/>
<desc>
- <p>If VM is in Unicode filename mode, <c>string()</c> and <c>char()</c>
+ <p>If VM is in Unicode filename mode, characters
are allowed to be &gt; 255.
<c><anno>RawFilename</anno></c> is a filename not subject to
Unicode translation,
meaning that it can contain characters not conforming to
the Unicode encoding expected from the file system
(that is, non-UTF-8 characters although the VM is started
- in Unicode filename mode).
+ in Unicode filename mode). Null characters (integer value zero)
+ are <em>not</em> allowed in filenames (not even at the end).
</p>
</desc>
</datatype>
@@ -954,8 +981,7 @@ f.txt: {person, "kalle", 25}.
</item>
<tag><c>eisdir</c></tag>
<item>
- <p>The named file is not a regular file. It can be a
- directory, a FIFO, or a device.</p>
+ <p>The named file is a directory.</p>
</item>
<tag><c>enotdir</c></tag>
<item>
@@ -1407,8 +1433,12 @@ f.txt: {person, "kalle", 25}.
which is 1970-01-01 00:00 UTC.</p></item>
</taglist>
<p>Default is <c>{time, local}</c>.</p>
- <p>If the option <c>raw</c> is set, the file server is not called
- and only information about local files is returned.</p>
+ <p>If the option <c>raw</c> is set, the file server is not called and
+ only information about local files is returned. Note that this will
+ break this module's atomicity guarantees as it can race with a
+ concurrent call to
+ <seealso marker="#write_file_info/2"><c>write_file_info/1,2</c>
+ </seealso></p>
<note>
<p>As file times are stored in POSIX time on most OS, it is faster to
query file information with option <c>posix</c>.</p>
@@ -1656,8 +1686,12 @@ f.txt: {person, "kalle", 25}.
except that if <c><anno>Name</anno></c> is a symbolic link, information
about the link is returned in the <c>file_info</c> record and
the <c>type</c> field of the record is set to <c>symlink</c>.</p>
- <p>If the option <c>raw</c> is set, the file server is not called
- and only information about local files is returned.</p>
+ <p>If the option <c>raw</c> is set, the file server is not called and
+ only information about local files is returned. Note that this will
+ break this module's atomicity guarantees as it can race with a
+ concurrent call to
+ <seealso marker="#write_file_info/2"><c>write_file_info/1,2</c>
+ </seealso></p>
<p>If <c><anno>Name</anno></c> is not a symbolic link, this function returns
the same result as <c>read_file_info/1</c>.
On platforms that do not support symbolic links, this function
@@ -1795,24 +1829,16 @@ f.txt: {person, "kalle", 25}.
<p>The file used must be opened using the <c>raw</c> flag, and the process
calling <c>sendfile</c> must be the controlling process of the socket.
See <seealso marker="gen_tcp#controlling_process-2"><c>gen_tcp:controlling_process/2</c></seealso>.</p>
- <p>If the OS used does not support <c>sendfile</c>, an Erlang fallback
- using
- <seealso marker="#read/2"><c>read/2</c></seealso> and
- <seealso marker="gen_tcp#send/2"><c>gen_tcp:send/2</c></seealso> is used.</p>
+ <p>If the OS used does not support non-blocking <c>sendfile</c>, an
+ Erlang fallback using <seealso marker="#read/2"><c>read/2</c></seealso>
+ and <seealso marker="gen_tcp#send/2"><c>gen_tcp:send/2</c></seealso> is
+ used.</p>
<p>The option list can contain the following options:</p>
<taglist>
<tag><c>chunk_size</c></tag>
<item><p>The chunk size used by the Erlang fallback to send
data. If using the fallback, set this to a value
that comfortably fits in the systems memory. Default is 20 MB.</p></item>
- <tag><c>use_threads</c></tag>
- <item><p>Instructs the emulator to use the <c>async</c> thread pool for the
- <c>sendfile</c> system call. This can be useful if the OS you are running
- on does not properly support non-blocking <c>sendfile</c> calls. Notice that
- using <c>async</c> threads potentially makes your system vulnerable to slow
- client attacks. If set to <c>true</c> and no <c>async</c> threads are available,
- the <c>sendfile</c> call returns <c>{error,einval}</c>.
- Introduced in Erlang/OTP 17.0. Default is <c>false</c>.</p></item>
</taglist>
</desc>
</func>
@@ -1825,7 +1851,7 @@ f.txt: {person, "kalle", 25}.
<p>The functions in the module <c>file</c> usually treat binaries
as raw filenames, that is, they are passed "as is" even when the
encoding of the binary does not agree with
- <seealso marker="#native_name_encoding"><c>native_name_encoding()</c></seealso>.
+ <seealso marker="#native_name_encoding/0"><c>native_name_encoding()</c></seealso>.
However, this function expects binaries to be encoded according to the
value returned by <c>native_name_encoding()</c>.</p>
<p>Typical error reasons are:</p>
@@ -2117,144 +2143,77 @@ f.txt: {person, "kalle", 25}.
<section>
<title>Performance</title>
- <p>Some operating system file operations, for example, a
- <c>sync/1</c> or <c>close/1</c> on a huge file, can block their
- calling thread for seconds. If this affects the emulator main
- thread, the response time is no longer in the order of
- milliseconds, depending on the definition of "soft" in soft
- real-time system.</p>
- <p>If the device driver thread pool is active, file operations are
- done through those threads instead, so the emulator can go on
- executing Erlang processes. Unfortunately, the time for serving a
- file operation increases because of the extra scheduling required
- from the operating system.</p>
- <p>If the device driver thread pool is disabled or of size 0, large
- file reads and writes are segmented into many smaller, which
- enable the emulator to serve other processes during the file
- operation. This has the same effect as when using the thread
- pool, but with larger overhead. Other file operations, for
- example, <c>sync/1</c> or <c>close/1</c> on a huge file, still are
- a problem.</p>
- <p>For increased performance, raw files are recommended. Raw files
- use the file system of the host machine of the node.</p>
+ <p>For increased performance, raw files are recommended.</p>
+ <p>A normal file is really a process so it can be used as an I/O
+ device (see <seealso marker="stdlib:io"><c>io</c></seealso>).
+ Therefore, when data is written to a normal file, the sending of the
+ data to the file process, copies all data that are not binaries. Opening
+ the file in binary mode and writing binaries is therefore recommended.
+ If the file is opened on another node, or if the file server runs as
+ slave to the file server of another node, also binaries are copied.</p>
<note>
- <p>
- For normal files (non-raw), the file server is used to find the files,
- and if the node is running its file server as slave to the file server
- of another node, and the other node runs on some other host machine,
- they can have different file systems.
- However, this is seldom a problem.</p>
+ <p>Raw files use the file system of the host machine of the node.
+ For normal files (non-raw), the file server is used to find the files,
+ and if the node is running its file server as slave to the file server
+ of another node, and the other node runs on some other host machine,
+ they can have different file systems.
+ However, this is seldom a problem.</p>
</note>
- <p>A normal file is really a process so it can be used as an I/O
- device (see
- <seealso marker="stdlib:io"><c>io</c></seealso>).
- Therefore, when data is written to a
- normal file, the sending of the data to the file process, copies
- all data that are not binaries. Opening the file in binary mode
- and writing binaries is therefore recommended. If the file is
- opened on another node, or if the file server runs as slave to
- the file server of another node, also binaries are copied.</p>
- <p>Caching data to reduce the number of file operations, or rather
- the number of calls to the file driver, generally increases
- performance. The following function writes 4 MBytes in 23
- seconds when tested:</p>
+ <p><seealso marker="#open/2"><c>open/2</c></seealso> can be given the
+ options <c>delayed_write</c> and <c>read_ahead</c> to turn on caching,
+ which will reduce the number of operating system calls and greatly
+ improve performance for small reads and writes. However, the overhead
+ won't disappear completely and it's best to keep the number of file
+ operations to a minimum. As a contrived example, the following function
+ writes 4MB in 2.5 seconds when tested:</p>
+
<code type="none"><![CDATA[
-create_file_slow(Name, N) when integer(N), N >= 0 ->
- {ok, FD} = file:open(Name, [raw, write, delayed_write, binary]),
- ok = create_file_slow(FD, 0, N),
- ok = ?FILE_MODULE:close(FD),
- ok.
-
-create_file_slow(FD, M, M) ->
+create_file_slow(Name) ->
+ {ok, Fd} = file:open(Name, [raw, write, delayed_write, binary]),
+ create_file_slow_1(Fd, 4 bsl 20),
+ file:close(Fd).
+
+create_file_slow_1(_Fd, 0) ->
ok;
-create_file_slow(FD, M, N) ->
- ok = file:write(FD, <<M:32/unsigned>>),
- create_file_slow(FD, M+1, N).]]></code>
+create_file_slow_1(Fd, M) ->
+ ok = file:write(Fd, <<0>>),
+ create_file_slow_1(Fd, M - 1).]]></code>
+
+ <p>The following functionally equivalent code writes 128 bytes per call
+ to <seealso marker="#write/2"><c>write/2</c></seealso> and so does the
+ same work in 0.08 seconds, which is roughly 30 times faster:</p>
- <p>The following, functionally equivalent, function collects 1024
- entries into a list of 128 32-byte binaries before each call to
- <seealso marker="#write/2"><c>write/2</c></seealso> and so
- does the same work in 0.52 seconds,
- which is 44 times faster:</p>
<code type="none"><![CDATA[
-create_file(Name, N) when integer(N), N >= 0 ->
- {ok, FD} = file:open(Name, [raw, write, delayed_write, binary]),
- ok = create_file(FD, 0, N),
- ok = ?FILE_MODULE:close(FD),
+create_file(Name) ->
+ {ok, Fd} = file:open(Name, [raw, write, delayed_write, binary]),
+ create_file_1(Fd, 4 bsl 20),
+ file:close(Fd),
ok.
-
-create_file(FD, M, M) ->
+
+create_file_1(_Fd, 0) ->
ok;
-create_file(FD, M, N) when M + 1024 =&lt; N ->
- create_file(FD, M, M + 1024, []),
- create_file(FD, M + 1024, N);
-create_file(FD, M, N) ->
- create_file(FD, M, N, []).
-
-create_file(FD, M, M, R) ->
- ok = file:write(FD, R);
-create_file(FD, M, N0, R) when M + 8 =&lt; N0 ->
- N1 = N0-1, N2 = N0-2, N3 = N0-3, N4 = N0-4,
- N5 = N0-5, N6 = N0-6, N7 = N0-7, N8 = N0-8,
- create_file(FD, M, N8,
- [<<N8:32/unsigned, N7:32/unsigned,
- N6:32/unsigned, N5:32/unsigned,
- N4:32/unsigned, N3:32/unsigned,
- N2:32/unsigned, N1:32/unsigned>> | R]);
-create_file(FD, M, N0, R) ->
- N1 = N0-1,
- create_file(FD, M, N1, [<<N1:32/unsigned>> | R]).]]></code>
+create_file_1(Fd, M) when M >= 128 ->
+ ok = file:write(Fd, <<0:(128)/unit:8>>),
+ create_file_1(Fd, M - 128);
+create_file_1(Fd, M) ->
+ ok = file:write(Fd, <<0:(M)/unit:8>>),
+ create_file_1(Fd, M - 1).]]></code>
- <note>
- <p>Trust only your own benchmarks. If the list length in
- <c>create_file/2</c> above is increased, it runs slightly
- faster, but consumes more memory and causes more memory
- fragmentation. How much this affects your application is
- something that this simple benchmark cannot predict.</p>
- <p>If the size of each binary is increased to 64 bytes, it
- also runs slightly faster, but the code is then twice as clumsy.
- In the current implementation, binaries larger than 64 bytes are
- stored in memory common to all processes and not copied when
- sent between processes, while these smaller binaries are stored
- on the process heap and copied when sent like any other term.</p>
- <p>So, with a binary size of 68 bytes, <c>create_file/2</c> runs
- 30 percent slower than with 64 bytes, and causes much more
- memory fragmentation. Notice that if the binaries were to be sent
- between processes (for example, a non-raw file), the results
- would probably be completely different.</p>
- </note>
- <p>A raw file is really a port. When writing data to a port, it is
- efficient to write a list of binaries. It is not needed to
- flatten a deep list before writing. On Unix hosts, scatter output,
- which writes a set of buffers in one operation, is used when
- possible. In this way <c>write(FD, [Bin1, Bin2 | Bin3])</c>
- writes the contents of the binaries without copying the data
- at all, except for perhaps deep down in the operating system
- kernel.</p>
- <p>For raw files, <c>pwrite/2</c> and <c>pread/2</c> are
- efficiently implemented. The file driver is called only once for
- the whole operation, and the list iteration is done in the file
- driver.</p>
- <p>The options <c>delayed_write</c> and <c>read_ahead</c> to
- <seealso marker="#open/2"><c>open/2</c></seealso>
- make the file driver cache data to reduce
- the number of operating system calls. The function
- <c>create_file/2</c> in the recent example takes 60 seconds
- without option <c>delayed_write</c>, which is 2.6
- times slower.</p>
- <p>As a bad example, <c>create_file_slow/2</c>
- without options <c>raw</c>, <c>binary</c>, and <c>delayed_write</c>,
- meaning it calls <c>open(Name, [write])</c>, needs
- 1 min 20 seconds for the job, which is 3.5 times slower than
- the first example, and 150 times slower than the optimized
- <c>create_file/2</c>.</p>
- <warning>
- <p>If an error occurs when accessing an open file with module
- <seealso marker="stdlib:io"><c>io</c></seealso>,
- the process handling the file exits. The dead
- file process can hang if a process tries to access it later.
- This will be fixed in a future release.</p>
- </warning>
+ <p>When writing data it's generally more efficient to write a list of
+ binaries rather than a list of integers. It is not needed to
+ flatten a deep list before writing. On Unix hosts, scatter output,
+ which writes a set of buffers in one operation, is used when
+ possible. In this way <c>write(FD, [Bin1, Bin2 | Bin3])</c>
+ writes the contents of the binaries without copying the data
+ at all, except for perhaps deep down in the operating system
+ kernel.</p>
+ <warning>
+ <p>If an error occurs when accessing an open file with module
+ <seealso marker="stdlib:io"><c>io</c></seealso>, the process
+ handling the file exits. The dead file process can hang if a process
+ tries to access it later. This will be fixed in a future release.
+ </p>
+ </warning>
</section>
<section>
diff --git a/lib/kernel/doc/src/heart.xml b/lib/kernel/doc/src/heart.xml
index 5b5b71e521..ad1a2ffeb9 100644
--- a/lib/kernel/doc/src/heart.xml
+++ b/lib/kernel/doc/src/heart.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -59,8 +59,9 @@
<pre>
% <input>erl -heart -env HEART_BEAT_TIMEOUT 30 ...</input></pre>
<p>The value (in seconds) must be in the range 10 &lt; X &lt;= 65535.</p>
- <p>Notice that if the system clock is adjusted with
- more than <c>HEART_BEAT_TIMEOUT</c> seconds, <c>heart</c>
+ <p>When running on OSs lacking support for monotonic time,
+ <c>heart</c> is susceptible to system clock adjustments of more than
+ <c>HEART_BEAT_TIMEOUT</c> seconds. When this happens, <c>heart</c>
times out and tries to reboot the system. This can occur, for
example, if the system clock is adjusted automatically by use of the
Network Time Protocol (NTP).</p>
diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml
index 169a76463b..e6a7962c5a 100644
--- a/lib/kernel/doc/src/inet.xml
+++ b/lib/kernel/doc/src/inet.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2017</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -197,6 +197,9 @@ fe80::204:acff:fe17:bf38
<datatype>
<name name="address_family"/>
</datatype>
+ <datatype>
+ <name name="socket_protocol"/>
+ </datatype>
</datatypes>
<funcs>
@@ -274,9 +277,7 @@ fe80::204:acff:fe17:bf38
<p>Returns a <c>hostent</c> record for the host with the specified
hostname.</p>
<p>If resolver option <c>inet6</c> is <c>true</c>,
- an IPv6 address is looked up. If that fails,
- the IPv4 address is looked up and returned on
- IPv6-mapped IPv4 format.</p>
+ an IPv6 address is looked up.</p>
</desc>
</func>
@@ -461,6 +462,61 @@ get_tcpi_sacked(Sock) ->
</func>
<func>
+ <name name="i" arity="0" />
+ <name name="i" arity="1" />
+ <name name="i" arity="2" />
+ <fsummary>Displays information and statistics about sockets on the terminal</fsummary>
+ <desc>
+ <p>
+ Lists all TCP, UDP and SCTP sockets, including those that the Erlang runtime system uses as well as
+ those created by the application.
+ </p>
+ <p>
+ The following options are available:
+ </p>
+
+ <taglist>
+ <tag><c>port</c></tag>
+ <item>
+ <p>The internal index of the port.</p>
+ </item>
+ <tag><c>module</c></tag>
+ <item>
+ <p>The callback module of the socket.</p>
+ </item>
+ <tag><c>recv</c></tag>
+ <item>
+ <p>Number of bytes received by the socket.</p>
+ </item>
+ <tag><c>sent</c></tag>
+ <item>
+ <p>Number of bytes sent from the socket.</p>
+ </item>
+ <tag><c>owner</c></tag>
+ <item>
+ <p>The socket owner process.</p>
+ </item>
+ <tag><c>local_address</c></tag>
+ <item>
+ <p>The local address of the socket.</p>
+ </item>
+ <tag><c>foreign_address</c></tag>
+ <item>
+ <p>The address and port of the other end of the connection.</p>
+ </item>
+ <tag><c>state</c></tag>
+ <item>
+ <p>The connection state.</p>
+ </item>
+ <tag><c>type</c></tag>
+ <item>
+ <p>STREAM or DGRAM or SEQPACKET.</p>
+ </item>
+ </taglist>
+ </desc>
+ </func>
+
+ <func>
<name name="ntoa" arity="1" />
<fsummary>Convert IPv6/IPV4 address to ASCII.</fsummary>
<desc>
@@ -524,6 +580,19 @@ get_tcpi_sacked(Sock) ->
</func>
<func>
+ <name name="ipv4_mapped_ipv6_address" arity="1" />
+ <fsummary>Convert to and from IPv4-mapped IPv6 address.</fsummary>
+ <desc>
+ <p>
+ Convert an IPv4 address to an IPv4-mapped IPv6 address
+ or the reverse. When converting from an IPv6 address
+ all but the 2 low words are ignored so this function also
+ works on some other types of addresses than IPv4-mapped.
+ </p>
+ </desc>
+ </func>
+
+ <func>
<name name="parse_strict_address" arity="1" />
<fsummary>Parse an IPv4 or IPv6 address strict.</fsummary>
<desc>
@@ -1080,7 +1149,7 @@ setcap cap_sys_admin,cap_sys_ptrace,cap_dac_read_search+epi beam.smp</code>
<seealso marker="gen_tcp#recv/2"><c>gen_tcp:recv/2</c></seealso>
gets <c>{error, closed}</c>. In active
mode, the controlling process receives a
- <c>{tcp_close, Socket}</c> message, indicating that the
+ <c>{tcp_closed, Socket}</c> message, indicating that the
peer has closed the connection.</p>
<p>Setting this option to <c>true</c> allows you to
distinguish between a connection that was closed normally,
@@ -1214,7 +1283,7 @@ inet:setopts(Sock,[{raw,6,8,<<30:32/native>>}]),]]></code>
For one-to-many style sockets, the special value <c>0</c>
is defined to mean that the returned addresses must be
without any particular association.
- How different SCTP implementations interprets this varies somewhat.
+ How different SCTP implementations interpret this varies somewhat.
</p>
</desc>
</func>
diff --git a/lib/kernel/doc/src/inet_res.xml b/lib/kernel/doc/src/inet_res.xml
index 4ada4203c0..351d86a93a 100644
--- a/lib/kernel/doc/src/inet_res.xml
+++ b/lib/kernel/doc/src/inet_res.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>2009</year><year>2015</year>
+ <year>2009</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -130,7 +130,7 @@ dns_header() = DnsHeader
inet_dns:header(DnsHeader) ->
[ {id, integer()}
| {qr, boolean()}
- | {opcode, 'query' | iquery | status | integer()}
+ | {opcode, query | iquery | status | integer()}
| {aa, boolean()}
| {tc, boolean()}
| {rd, boolean()}
@@ -230,9 +230,7 @@ inet_dns:record_type(_) -> undefined.</pre>
<seealso marker="#getbyname/2"><c>getbyname/2,3</c></seealso>.
</p>
<p>If resolver option <c>inet6</c> is <c>true</c>,
- an IPv6 address is looked up. If that fails,
- the IPv4 address is looked up and returned on
- IPv6-mapped IPv4 format.</p>
+ an IPv6 address is looked up.</p>
</desc>
</func>
diff --git a/lib/kernel/doc/src/introduction_chapter.xml b/lib/kernel/doc/src/introduction_chapter.xml
new file mode 100644
index 0000000000..d02b1a2ee5
--- /dev/null
+++ b/lib/kernel/doc/src/introduction_chapter.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2017</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>Introduction</title>
+ <prepared></prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <approved></approved>
+ <checked></checked>
+ <date></date>
+ <rev></rev>
+ <file>introduction.xml</file>
+ </header>
+
+ <section>
+ <title>Scope</title>
+ <p>The Kernel application has all the code necessary to run
+ the Erlang runtime system: file servers, code servers,
+ and so on.</p>
+ <p>The Kernel application is the first application started. It is
+ mandatory in the sense that the minimal system based on
+ Erlang/OTP consists of Kernel and STDLIB. Kernel
+ contains the following functional areas:</p>
+ <list type="bulleted">
+ <item>Start, stop, supervision, configuration, and distribution of applications</item>
+ <item>Code loading</item>
+ <item>Logging</item>
+ <item>Global name service</item>
+ <item>Supervision of Erlang/OTP</item>
+ <item>Communication with sockets</item>
+ <item>Operating system interface</item>
+ </list>
+ </section>
+
+ <section>
+ <title>Prerequisites</title>
+ <p>It is assumed that the reader is familiar with the Erlang programming
+ language.</p>
+ </section>
+</chapter>
+
+
diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml
index 0762cebc94..ccb7d17d25 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>
@@ -51,10 +50,13 @@
</description>
<section>
- <title>Error Logger Event Handlers</title>
- <p>Two standard error logger event handlers are defined in
- the Kernel application. These are described in
- <seealso marker="error_logger"><c>error_logger(3)</c></seealso>.</p>
+ <title>Logger Handlers</title>
+ <p>Two standard logger handlers are defined in
+ the Kernel application. These are described in the
+ <seealso marker="logger_chapter">Kernel User's Guide</seealso>,
+ and in the <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> manual pages.</p>
</section>
<section>
@@ -113,26 +115,12 @@
</section>
<section>
+ <marker id="configuration"/>
<title>Configuration</title>
<p>The following configuration parameters are defined for the Kernel
application. For more information about configuration parameters,
see file <seealso marker="app"><c>app(4)</c></seealso>.</p>
<taglist>
- <tag><c>browser_cmd = string() | {M,F,A}</c></tag>
- <item>
- <p>When pressing the <em>Help</em> button in a tool such as Debugger,
- the help text (an HTML file <c>File</c>) is by default
- displayed in a Netscape browser, which is required to be
- operational. This parameter can be used to change the command for
- how to display the help text if another browser than Netscape
- is preferred, or if another platform than Unix or Windows is
- used.</p>
- <p>If set to a string <c>Command</c>, the command
- <c>"Command File"</c> is evaluated using
- <seealso marker="os#cmd/1"><c>os:cmd/1</c></seealso>.</p>
- <p>If set to a module-function-args tuple, <c>{M,F,A}</c>,
- the call <c>apply(M,F,[File|A])</c> is evaluated.</p>
- </item>
<tag><c>distributed = [Distrib]</c></tag>
<item>
<p>Specifies which applications that are distributed and on which
@@ -176,65 +164,74 @@
<p>Permissions are described in
<seealso marker="application#permit/2"><c>application:permit/2</c></seealso>.</p>
</item>
- <tag><c>error_logger = Value</c></tag>
- <item>
- <p><c>Value</c> is one of:</p>
- <taglist>
- <tag><c>tty</c></tag>
- <item><p>Installs the standard event handler, which prints error
- reports to <c>stdio</c>. This is the default option.</p></item>
- <tag><c>{file, FileName}</c></tag>
- <item><p>Installs the standard event handler, which prints error
- reports to file <c>FileName</c>, where <c>FileName</c>
- is a string. The file is opened with encoding UTF-8.</p></item>
- <tag><c>false</c></tag>
- <item>
- <p>No standard event handler is installed, but
- the initial, primitive event handler is kept, printing
- raw event messages to <c>tty</c>.</p>
- </item>
- <tag><c>silent</c></tag>
- <item>
- <p>Error logging is turned off.</p>
- </item>
- </taglist>
+ <tag><marker id="logger"/><c>logger = [Config]</c></tag>
+ <item>
+ <p>Specifies the configuration
+ for <seealso marker="logger">Logger</seealso>, except the
+ primary log level, which is specified
+ with <seealso marker="#logger_level"><c>logger_level</c></seealso>,
+ and the compatibility
+ with <seealso marker="sasl:error_logging">SASL Error
+ Logging</seealso>, which is specified
+ with <seealso marker="#logger_sasl_compatible">
+ <c>logger_sasl_compatible</c></seealso>.</p>
+ <p>The <c>logger </c> parameter is described in
+ section <seealso marker="logger_chapter#logger_parameter">
+ Logging</seealso> in the Kernel User's Guide.</p>
+ </item>
+ <tag><marker id="logger_level"/><c>logger_level = Level</c></tag>
+ <item>
+ <p>Specifies the primary log level for Logger. Log events with
+ the same, or a more severe level, pass through the primary
+ log level check. See
+ section <seealso marker="logger_chapter">Logging</seealso>
+ in the Kernel User's Guide for more information about Logger
+ and log levels.</p>
+ <p><c>Level = emergency | alert | critical | error | warning |
+ notice | info | debug | all | none</c></p>
+ <p>To change the primary log level at runtime, use
+ <seealso marker="logger#set_primary_config/2">
+ <c>logger:set_primary_config(level, Level)</c></seealso>.</p>
+ <p>Defaults to <c>info</c>.</p>
+ </item>
+ <tag><marker id="logger_sasl_compatible"/>
+ <c>logger_sasl_compatible = true | false</c></tag>
+ <item>
+ <p>Specifies if Logger behaves backwards compatible with the
+ SASL error logging functionality from releases prior to
+ Erlang/OTP 21.0.</p>
+ <p>If this parameter is set to <c>true</c>, the default Logger
+ handler does not log any progress-, crash-, or supervisor
+ reports. If the SASL application is then started, it adds a
+ Logger handler named <c>sasl</c>, which logs these events
+ according to values of the SASL configuration
+ parameter <c>sasl_error_logger</c>
+ and <c>sasl_errlog_type</c>.</p>
+ <p>See section
+ <seealso marker="sasl:sasl_app#deprecated_error_logger_config">
+ Deprecated Error Logger Event Handlers and
+ Configuration</seealso> in the sasl(6) manual page for
+ information about the SASL configuration parameters.</p>
+ <p>See section <seealso marker="sasl:error_logging">SASL Error
+ Logging</seealso> in the SASL User's Guide, and
+ section <seealso marker="logger_chapter#compatibility">Backwards
+ Compatibility with error_logger</seealso> in the Kernel
+ User's Guide for information about the SASL error logging
+ functionality, and how Logger can be backwards compatible
+ with this.</p>
+ <p>Defaults to <c>false</c>.</p>
+ <note>
+ <p>If this parameter is set to <c>true</c>,
+ <c>sasl_errlog_type</c> indicates that progress reports
+ shall be logged, and the configured primary log level
+ is <c>notice</c> or more severe, then SASL automatically
+ sets the primary log level to <c>info</c>. That is, this
+ setting can potentially overwrite the value of the Kernel
+ configuration parameter <c>logger_level</c>. This is to
+ allow progress reports, which have log level <c>info</c>,
+ to be forwarded to the handlers.</p>
+ </note>
</item>
- <tag><c>error_logger_format_depth = Depth</c></tag>
- <item>
- <marker id="error_logger_format_depth"></marker>
- <p>Can be used to limit the size of the
- formatted output from the error logger event handlers.</p>
-
- <note><p>This configuration parameter was introduced in OTP 18.1
- and is experimental. Based on user feedback, it
- can be changed or improved in future releases, for example,
- to gain better control over how to limit the size of the
- formatted output. We have no plans to remove this
- new feature entirely, unless it turns out to be
- useless.</p></note>
-
- <p><c>Depth</c> is a positive integer representing the maximum
- depth to which terms are printed by the error logger event
- handlers included in OTP. This
- configuration parameter is used by the two event handlers
- defined by the Kernel application and the two event
- handlers in the SASL application.
- (If you have implemented your own error handlers, this configuration
- parameter has no effect on them.)</p>
-
- <p><c>Depth</c> is used as follows: Format strings
- passed to the event handlers are rewritten.
- The format controls <c>~p</c> and <c>~w</c> are replaced with
- <c>~P</c> and <c>~W</c>, respectively, and <c>Depth</c> is
- used as the depth parameter. For details, see
- <seealso marker="stdlib:io#format/2"><c>io:format/2</c></seealso>
- in STDLIB.</p>
-
- <note><p>A reasonable starting value for <c>Depth</c> is
- <c>30</c>. We recommend to test crashing various processes in your
- application, examine the logs from the crashes, and then
- increase or decrease the value.</p></note>
- </item>
<tag><c>global_groups = [GroupTuple]</c></tag>
<item>
<marker id="global_groups"></marker>
@@ -286,9 +283,8 @@
</item>
<tag><c>inet_parse_error_log = silent</c></tag>
<item>
- <p>If set, no
- <c>error_logger</c> messages are generated when erroneous
- lines are found and skipped in the various Inet configuration
+ <p>If set, no log events are issued when erroneous lines are
+ found and skipped in the various Inet configuration
files.</p>
</item>
<tag><c>inetrc = Filename</c></tag>
@@ -314,24 +310,31 @@
<tag><c>net_ticktime = TickTime</c></tag>
<item>
<marker id="net_ticktime"></marker>
- <p>Specifies the <c>net_kernel</c> tick time. <c>TickTime</c>
- is specified in seconds. Once every <c>TickTime/4</c> second, all
- connected nodes are ticked (if anything else is written
- to a node). If nothing is received from another node
- within the last four tick times, that node is considered
- to be down. This ensures that nodes that are not responding,
- for reasons such as hardware errors, are considered to be
- down.</p>
- <p>The time <c>T</c>, in which a node that is not responding is
- detected, is calculated as <c><![CDATA[MinT < T < MaxT]]></c>, where:</p>
+ <p>Specifies the <c>net_kernel</c> tick time in seconds. This is the
+ approximate time a connected node may be unresponsive until it is
+ considered down and thereby disconnected.</p>
+ <p>Once every <c>TickTime/4</c> seconds, each connected node is ticked
+ if nothing has been sent to it during that last <c>TickTime/4</c>
+ interval. A tick is a small package sent on the connection. A connected
+ node is considered to be down if no ticks or payload packages have been
+ received during the last four <c>TickTime/4</c> intervals. This ensures
+ that nodes that are not responding, for reasons such as hardware errors,
+ are considered to be down.</p>
+ <p>As the availability is only checked every <c>TickTime/4</c> seconds,
+ the actual time <c>T</c> a node have been unresponsive when
+ detected may vary between <c>MinT</c> and <c>MaxT</c>,
+ where:</p>
<code type="none">
MinT = TickTime - TickTime / 4
MaxT = TickTime + TickTime / 4</code>
- <p><c>TickTime</c> defaults to <c>60</c> (seconds). Thus,
- <c><![CDATA[45 < T < 75]]></c> seconds.</p>
- <p>Notice that <em>all</em> communicating nodes are to have the <em>same</em>
- <c>TickTime</c> value specified.</p>
- <p>Normally, a terminating node is detected immediately.</p>
+ <p><c>TickTime</c> defaults to <c>60</c> seconds. Thus,
+ <c><![CDATA[45 < T < 75]]></c> seconds.</p>
+ <p>Notice that <em>all</em> communicating nodes are to have the
+ <em>same</em> <c>TickTime</c> value specified, as it determines both the
+ frequency of outgoing ticks and the expected frequency of incominging
+ ticks.</p>
+ <p>Normally, a terminating node is detected immediately by the transport
+ protocol (like TCP/IP).</p>
</item>
<tag><c>shutdown_timeout = integer() | infinity</c></tag>
<item>
@@ -497,6 +500,37 @@ MaxT = TickTime + TickTime / 4</code>
</section>
<section>
+ <title>Deprecated Configuration Parameters</title>
+ <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, still work, but they are no longer used
+ by default.</p>
+ <p>The following application configuration parameters can still be
+ 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
+ <seealso marker="logger_std_h#type"><c>logger_std_h</c></seealso>
+ to the same value. Example:
+ <code type="none">
+erl -kernel logger '[{handler,default,logger_std_h,#{config=>#{type=>{file,"/tmp/erlang.log"}}}}]'
+ </code>
+ </item>
+ <tag><c>error_logger_format_depth</c></tag>
+ <item>Replaced by setting the <seealso marker="logger_formatter#depth"><c>depth</c></seealso>
+ parameter of the default handlers formatter. Example:
+ <code type="none">
+erl -kernel logger '[{handler,default,logger_std_h,#{formatter=>{logger_formatter,#{legacy_header=>true,template=>[{logger_formatter,header},"\n",msg,"\n"],depth=>10}}}]'
+ </code>
+ </item>
+ </taglist>
+ <p>See <seealso marker="logger_chapter#compatibility">Backwards
+ compatibility with error_logger</seealso> for more
+ information.</p>
+ </section>
+
+ <section>
<title>See Also</title>
<p><seealso marker="app"><c>app(4)</c></seealso>,
<seealso marker="application"><c>application(3)</c></seealso>,
@@ -504,12 +538,12 @@ MaxT = TickTime + TickTime / 4</code>
<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
new file mode 100644
index 0000000000..f1830a8224
--- /dev/null
+++ b/lib/kernel/doc/src/logger.xml
@@ -0,0 +1,1169 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2017</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>logger</title>
+ <prepared></prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <approved></approved>
+ <checked></checked>
+ <date></date>
+ <rev>A</rev>
+ <file>logger.xml</file>
+ </header>
+ <module>logger</module>
+ <modulesummary>API module for Logger, the standard logging facility
+ in Erlang/OTP.</modulesummary>
+
+ <description>
+ <p>This module implements the main API for logging in
+ Erlang/OTP. To create a log event, use the
+ <seealso marker="#logging_API">API functions</seealso> or the
+ log
+ <seealso marker="#macros">macros</seealso>, for example:</p>
+ <code>
+?LOG_ERROR("error happened because: ~p", [Reason]). % With macro
+logger:error("error happened because: ~p", [Reason]). % Without macro
+ </code>
+ <p>To configure the Logger backend,
+ use <seealso marker="kernel_app#logger">Kernel configuration
+ parameters</seealso>
+ or <seealso marker="#configuration_API">configuration
+ functions</seealso> in the Logger API.</p>
+
+ <p>By default, the Kernel application installs one log handler at
+ system start. This handler is named <c>default</c>. It receives
+ and processes standard log events produced by the Erlang runtime
+ system, standard behaviours and different Erlang/OTP
+ applications. The log events are by default printed to the
+ terminal.</p>
+ <p>If you want your systems logs to be printed to a file instead,
+ you 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,
+ [{logger,
+ [{handler, default, logger_std_h,
+ #{config => #{type => {file, "path/to/file.log"}}}}]}]}].
+ </code>
+ <p>
+ For more information about:
+ </p>
+ <list type="bulleted">
+ <item>the Logger facility in general, see
+ the <seealso marker="logger_chapter">User's
+ Guide</seealso>.</item>
+ <item>how to configure Logger, see
+ the <seealso marker="logger_chapter#configuration">Configuration</seealso>
+ section in the User's Guide.</item>
+ <item>the built-in handlers,
+ see <seealso marker="logger_std_h">logger_std_h</seealso> and
+ <seealso marker="logger_disk_log_h">logger_disk_log_h</seealso>.</item>
+ <item>the built-in formatter,
+ see <seealso marker="logger_formatter">logger_formatter</seealso>.</item>
+ <item>built-in filters,
+ see <seealso marker="logger_filters">logger_filters</seealso>.</item>
+ </list>
+
+ <note>
+ <p>Since Logger is new in Erlang/OTP 21.0, we do reserve the right
+ to introduce changes to the Logger API and functionality in
+ patches following this release. These changes might or might not
+ be backwards compatible with the initial version.</p>
+ </note>
+
+ </description>
+
+ <datatypes>
+ <datatype>
+ <name name="filter"/>
+ <desc>
+ <p>A filter which can be installed as a handler filter, or as
+ a primary filter in Logger.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="filter_arg"/>
+ <desc>
+ <p>The second argument to the filter fun.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="filter_id"/>
+ <desc>
+ <p>A unique identifier for a filter.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="filter_return"/>
+ <desc>
+ <p>The return value from the filter fun.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="formatter_config"/>
+ <desc>
+ <p>Configuration data for the
+ formatter. See <seealso marker="logger_formatter">
+ <c>logger_formatter(3)</c></seealso>
+ for an example of a formatter implementation.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="handler_config"/>
+ <desc>
+ <p>Handler configuration data for Logger. The following
+ default values apply:</p>
+ <list>
+ <item><c>level => all</c></item>
+ <item><c>filter_default => log</c></item>
+ <item><c>filters => []</c></item>
+ <item><c>formatter => {logger_formatter, DefaultFormatterConfig</c>}</item>
+ </list>
+ <p>In addition to these, the following fields are
+ automatically inserted by Logger, values taken from the
+ two first parameters
+ to <seealso marker="#add_handler-3"><c>add_handler/3</c></seealso>:</p>
+ <list>
+ <item><c>id => HandlerId</c></item>
+ <item><c>module => Module</c></item>
+ </list>
+ <p>These are read-only and cannot be changed in runtime.</p>
+ <p>Handler specific configuration data is inserted by the
+ handler callback itself, in a sub structure associated with
+ the field named <c>config</c>. See
+ the <seealso marker="logger_std_h"><c>logger_std_h(3)</c></seealso>
+ and <seealso marker="logger_disk_log_h"><c>logger_disk_log_h</c></seealso>
+ manual pages for information about the specifc configuration
+ for these handlers.</p>
+ <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>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="handler_id"/>
+ <desc>
+ <p>A unique identifier for a handler instance.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="level"/>
+ <desc>
+ <p>The severity level for the message to be logged.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="log_event"/>
+ <desc>
+ <p></p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="metadata"/>
+ <desc>
+ <p>Metadata for the log event.</p>
+ <p>Logger adds the following metadata to each log event:</p>
+ <list>
+ <item><c>pid => self()</c></item>
+ <item><c>gl => group_leader()</c></item>
+ <item><c>time => erlang:system_time(microsecond)</c></item>
+ </list>
+ <p>When a log macro is used, Logger also inserts location
+ information:</p>
+ <list>
+ <item><c>mfa => {?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY}</c></item>
+ <item><c>file => ?FILE</c></item>
+ <item><c>line => ?LINE</c></item>
+ </list>
+ <p>You can add custom metadata, either by specifying a map as
+ the last parameter to any of the log macros or the API
+ functions, or by setting process metadata
+ with <seealso marker="#set_process_metadata-1">
+ <c>set_process_metadata/1</c></seealso>
+ or <seealso marker="#update_process_metadata-1">
+ <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 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, or directly to a string. See the
+ type definition
+ of <seealso marker="#type-report_cb"><c>report_cb()</c></seealso>,
+ and
+ 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>
+ <name name="msg_fun"/>
+ <desc>
+ <p></p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="primary_config"/>
+ <desc>
+ <p>Primary configuration data for Logger. The following
+ default values apply:</p>
+ <list>
+ <item><c>level => info</c></item>
+ <item><c>filter_default => log</c></item>
+ <item><c>filters => []</c></item>
+ </list>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="report"/>
+ <desc>
+ <p></p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="report_cb"/>
+ <desc>
+ <p>A fun which converts a <seealso marker="#type-report"><c>report()</c>
+ </seealso> to a format string and arguments, or directly to a string.
+ See section <seealso marker="logger_chapter#log_message">Log
+ Message</seealso> in the User's Guide for more
+ information.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="report_cb_config"/>
+ <desc>
+ <p></p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="timestamp"/>
+ <desc>
+ <p>A timestamp produced
+ with <seealso marker="erts:erlang#system_time-1">
+ <c>erlang:system_time(microsecond)</c></seealso>.</p>
+ </desc>
+ </datatype>
+ </datatypes>
+
+ <section>
+ <title>Macros</title>
+ <p>The following macros are defined:</p>
+
+ <list>
+ <item><c>?LOG_EMERGENCY(StringOrReport[,Metadata])</c></item>
+ <item><c>?LOG_EMERGENCY(FunOrFormat,Args[,Metadata])</c></item>
+ <item><c>?LOG_ALERT(StringOrReport[,Metadata])</c></item>
+ <item><c>?LOG_ALERT(FunOrFormat,Args[,Metadata])</c></item>
+ <item><c>?LOG_CRITICAL(StringOrReport[,Metadata])</c></item>
+ <item><c>?LOG_CRITICAL(FunOrFormat,Args[,Metadata])</c></item>
+ <item><c>?LOG_ERROR(StringOrReport[,Metadata])</c></item>
+ <item><c>?LOG_ERROR(FunOrFormat,Args[,Metadata])</c></item>
+ <item><c>?LOG_WARNING(StringOrReport[,Metadata])</c></item>
+ <item><c>?LOG_WARNING(FunOrFormat,Args[,Metadata])</c></item>
+ <item><c>?LOG_NOTICE(StringOrReport[,Metadata])</c></item>
+ <item><c>?LOG_NOTICE(FunOrFormat,Args[,Metadata])</c></item>
+ <item><c>?LOG_INFO(StringOrReport[,Metadata])</c></item>
+ <item><c>?LOG_INFO(FunOrFormat,Args[,Metadata])</c></item>
+ <item><c>?LOG_DEBUG(StringOrReport[,Metadata])</c></item>
+ <item><c>?LOG_DEBUG(FunOrFormat,Args[,Metadata])</c></item>
+ <item><c>?LOG(Level,StringOrReport[,Metadata])</c></item>
+ <item><c>?LOG(Level,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, or from the first argument in the
+ case of the <c>?LOG</c> macro. Location data is added to the
+ metadata as described under
+ the <seealso marker="#type-metadata"><c>metadata()</c></seealso>
+ type definition.</p>
+
+ <p>The call is wrapped in a case statement and will be evaluated
+ only if <c>Level</c> is equal to or below the configured log
+ level.</p>
+ </section>
+
+ <section>
+ <marker id="logging_API"/>
+ <title>Logging API functions</title>
+ </section>
+ <funcs>
+ <func>
+ <name>emergency(StringOrReport[,Metadata])</name>
+ <name>emergency(Format,Args[,Metadata])</name>
+ <name>emergency(Fun,FunArgs[,Metadata])</name>
+ <fsummary>Logs the given message as level <c>emergency</c>.</fsummary>
+ <desc>
+ <p>Equivalent to
+ <seealso marker="#log-2"><c>log(emergency,...)</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>alert(StringOrReport[,Metadata])</name>
+ <name>alert(Format,Args[,Metadata])</name>
+ <name>alert(Fun,FunArgs[,Metadata])</name>
+ <fsummary>Logs the given message as level <c>alert</c>.</fsummary>
+ <desc>
+ <p>Equivalent to
+ <seealso marker="#log-2"><c>log(alert,...)</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>critical(StringOrReport[,Metadata])</name>
+ <name>critical(Format,Args[,Metadata])</name>
+ <name>critical(Fun,FunArgs[,Metadata])</name>
+ <fsummary>Logs the given message as level <c>critical</c>.</fsummary>
+ <desc>
+ <p>Equivalent to
+ <seealso marker="#log-2"><c>log(critical,...)</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>error(StringOrReport[,Metadata])</name>
+ <name>error(Format,Args[,Metadata])</name>
+ <name>error(Fun,FunArgs[,Metadata])</name>
+ <fsummary>Logs the given message as level <c>error</c>.</fsummary>
+ <desc>
+ <p>Equivalent to
+ <seealso marker="#log-2"><c>log(error,...)</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>warning(StringOrReport[,Metadata])</name>
+ <name>warning(Format,Args[,Metadata])</name>
+ <name>warning(Fun,FunArgs[,Metadata])</name>
+ <fsummary>Logs the given message as level <c>warning</c>.</fsummary>
+ <desc>
+ <p>Equivalent to
+ <seealso marker="#log-2"><c>log(warning,...)</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>notice(StringOrReport[,Metadata])</name>
+ <name>notice(Format,Args[,Metadata])</name>
+ <name>notice(Fun,FunArgs[,Metadata])</name>
+ <fsummary>Logs the given message as level <c>notice</c>.</fsummary>
+ <desc>
+ <p>Equivalent to
+ <seealso marker="#log-2"><c>log(notice,...)</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>info(StringOrReport[,Metadata])</name>
+ <name>info(Format,Args[,Metadata])</name>
+ <name>info(Fun,FunArgs[,Metadata])</name>
+ <fsummary>Logs the given message as level <c>info</c>.</fsummary>
+ <desc>
+ <p>Equivalent to
+ <seealso marker="#log-2"><c>log(info,...)</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>debug(StringOrReport[,Metadata])</name>
+ <name>debug(Format,Args[,Metadata])</name>
+ <name>debug(Fun,FunArgs[,Metadata])</name>
+ <fsummary>Logs the given message as level <c>debug</c>.</fsummary>
+ <desc>
+ <p>Equivalent to
+ <seealso marker="#log-2"><c>log(debug,...)</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="log" arity="2"/>
+ <name name="log" arity="3" clause_i="1"/>
+ <name name="log" arity="3" clause_i="2"/>
+ <name name="log" arity="3" clause_i="3"/>
+ <name name="log" arity="4" clause_i="1"/>
+ <name name="log" arity="4" clause_i="2"/>
+ <fsummary>Logs the given message.</fsummary>
+ <type variable="Level"/>
+ <type variable="StringOrReport" name_i="1"/>
+ <type variable="Format" name_i="3"/>
+ <type variable="Args" name_i="3"/>
+ <type variable="Fun" name_i="4"/>
+ <type variable="FunArgs" name_i="4"/>
+ <type variable="Metadata"/>
+ <desc>
+ <p>Log the given message.</p>
+ </desc>
+ </func>
+ </funcs>
+
+ <section>
+ <marker id="configuration_API"/>
+ <title>Configuration API functions</title>
+ </section>
+ <funcs>
+ <func>
+ <name name="add_handler" arity="3"/>
+ <fsummary>Add a handler with the given configuration.</fsummary>
+ <desc>
+ <p>Add a handler with the given configuration.</p>
+ <p><c><anno>HandlerId</anno></c> is a unique identifier which
+ must be used in all subsequent calls referring to this
+ handler.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="add_handler_filter" arity="3"/>
+ <fsummary>Add a filter to the specified handler.</fsummary>
+ <desc>
+ <p>Add a filter to the specified handler.</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>
+ <p>The return value of the fun specifies if a log event is to
+ be discarded or forwarded to the handler callback:</p>
+ <taglist>
+ <tag><c>log_event()</c></tag>
+ <item>
+ <p>The filter <em>passed</em>. The next handler filter, if
+ any, is applied. If no more filters exist for this
+ handler, the log event is forwarded to the handler
+ callback.</p>
+ </item>
+ <tag><c>stop</c></tag>
+ <item>
+ <p>The filter <em>did not pass</em>, and the log event is
+ immediately discarded.</p>
+ </item>
+ <tag><c>ignore</c></tag>
+ <item>
+ <p>The filter has no knowledge of the log event. The next
+ handler filter, if any, is applied. If no more filters
+ exist for this handler, the value of
+ the <c>filter_default</c> configuration parameter for
+ the handler specifies if the log event shall be
+ discarded or forwarded to the handler callback.</p>
+ </item>
+ </taglist>
+ <p>See
+ section <seealso marker="logger_chapter#filters">Filters</seealso>
+ in the User's Guide for more information about filters.</p>
+ <p>Some built-in filters exist. These are defined in
+ <seealso marker="logger_filters"><c>logger_filters</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="add_handlers" arity="1" clause_i="1"/>
+ <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>add_handlers/1</c> with its contents.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="add_handlers" arity="1" clause_i="2"/>
+ <fsummary>Setup logger handlers.</fsummary>
+ <type name="config_handler"/>
+ <desc>
+ <p>This function should be used by custom Logger handlers to make
+ configuration consistent no matter which handler the system uses.
+ 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(_, []) ->
+ case supervisor:start_link({local, my_sup}, my_sup, []) of
+ {ok, Pid} ->
+ ok = logger:add_handlers(my_app),
+ {ok, Pid, []};
+ Error -> Error
+ end.</code>
+ <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 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
+ [{handler, default, undefined}]}]},
+ {my_app,
+ [{logger,
+ %% Enable this handler as the default
+ [{handler, default, my_handler, #{}}]}]}].
+ </code>
+ </desc>
+ </func>
+
+ <func>
+ <name name="add_primary_filter" arity="2"/>
+ <fsummary>Add a primary filter to Logger.</fsummary>
+ <desc>
+ <p>Add a primary filter to 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>
+ <p>The return value of the fun specifies if a log event is to
+ be discarded or forwarded to the handlers:</p>
+ <taglist>
+ <tag><c>log_event()</c></tag>
+ <item>
+ <p>The filter <em>passed</em>. The next primary filter, if
+ any, is applied. If no more primary filters exist, the
+ log event is forwarded to the handler part of Logger,
+ where handler filters are applied.</p>
+ </item>
+ <tag><c>stop</c></tag>
+ <item>
+ <p>The filter <em>did not pass</em>, and the log event is
+ immediately discarded.</p>
+ </item>
+ <tag><c>ignore</c></tag>
+ <item>
+ <p>The filter has no knowledge of the log event. The next
+ primary filter, if any, is applied. If no more primary
+ filters exist, the value of the
+ primary <c>filter_default</c> configuration parameter
+ specifies if the log event shall be discarded or
+ forwarded to the handler part.</p>
+ </item>
+ </taglist>
+ <p>See section <seealso marker="logger_chapter#filters">
+ Filters</seealso> in the User's Guide for more information
+ about filters.</p>
+ <p>Some built-in filters exist. These are defined
+ in <seealso marker="logger_filters"><c>logger_filters</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="get_config" arity="0"/>
+ <fsummary>Look up the current Logger configuration</fsummary>
+ <desc>
+ <p>Look up all current Logger configuration, including primary
+ and handler configuration, and module level settings.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="get_handler_config" arity="0"/>
+ <fsummary>Look up the current configuration for all handlers.</fsummary>
+ <desc>
+ <p>Look up the current configuration for all handlers.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="get_handler_config" arity="1"/>
+ <fsummary>Look up the current configuration for the given
+ handler.</fsummary>
+ <desc>
+ <p>Look up the current configuration for the given handler.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="get_handler_ids" arity="0"/>
+ <fsummary>Look up the identities for all installed handlers.</fsummary>
+ <desc>
+ <p>Look up the identities for all installed handlers.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="get_primary_config" arity="0"/>
+ <fsummary>Look up the current primary configuration for Logger.</fsummary>
+ <desc>
+ <p>Look up the current primary configuration for Logger.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="get_module_level" arity="0"/>
+ <fsummary>Look up all current module levels.</fsummary>
+ <desc>
+ <p>Look up all current module levels. Returns a list
+ containing one <c>{Module,Level}</c> element for each module
+ for which the module level was previously set
+ with <seealso marker="#set_module_level-2">
+ <c>set_module_level/2</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="get_module_level" arity="1"/>
+ <fsummary>Look up the current level for the given modules.</fsummary>
+ <desc>
+ <p>Look up the current level for the given modules. Returns a
+ list containing one <c>{Module,Level}</c> element for each
+ of the given modules for which the module level was
+ previously set with <seealso marker="#set_module_level-2">
+ <c>set_module_level/2</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="get_process_metadata" arity="0"/>
+ <fsummary>Retrieve data set with set_process_metadata/1.</fsummary>
+ <desc>
+ <p>Retrieve data set
+ with <seealso marker="#set_process_metadata-1">
+ <c>set_process_metadata/1</c></seealso> or
+ <seealso marker="#update_process_metadata-1">
+ <c>update_process_metadata/1</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="remove_handler" arity="1"/>
+ <fsummary>Remove the handler with the specified identity.</fsummary>
+ <desc>
+ <p>Remove the handler identified by <c><anno>HandlerId</anno></c>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="remove_handler_filter" arity="2"/>
+ <fsummary>Remove a filter from the specified handler.</fsummary>
+ <desc>
+ <p>Remove the filter identified
+ by <c><anno>FilterId</anno></c> from the handler identified
+ by <c><anno>HandlerId</anno></c>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="remove_primary_filter" arity="1"/>
+ <fsummary>Remove a primary filter from Logger.</fsummary>
+ <desc>
+ <p>Remove the primary filter identified
+ by <c><anno>FilterId</anno></c> from Logger.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="set_handler_config" arity="2"/>
+ <fsummary>Set configuration data for the specified handler.</fsummary>
+ <desc>
+ <p>Set configuration data for the specified handler. This
+ overwrites the current handler configuration.</p>
+ <p>To modify the existing configuration,
+ use <seealso marker="#update_handler_config-2">
+ <c>update_handler_config/2</c></seealso>, or, if a more
+ complex merge is needed, read the current configuration
+ with <seealso marker="#get_handler_config-1"><c>get_handler_config/1</c>
+ </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 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>
+ </desc>
+ </func>
+
+ <func>
+ <name name="set_handler_config" arity="3" clause_i="1"/>
+ <name name="set_handler_config" arity="3" clause_i="2"/>
+ <name name="set_handler_config" arity="3" clause_i="3"/>
+ <name name="set_handler_config" arity="3" clause_i="4"/>
+ <name name="set_handler_config" arity="3" clause_i="5"/>
+ <fsummary>Add or update configuration data for the specified
+ handler.</fsummary>
+ <type variable="HandlerId"/>
+ <type variable="Level" name_i="1"/>
+ <type variable="FilterDefault" name_i="2"/>
+ <type variable="Filters" name_i="3"/>
+ <type variable="Formatter" name_i="4"/>
+ <type variable="Config" name_i="5"/>
+ <type variable="Return"/>
+ <desc>
+ <p>Add or update configuration data for the specified
+ handler. If the given <c><anno>Key</anno></c> already
+ exists, its associated value will be changed
+ to the given value. If it does not exist, it will
+ be added.</p>
+ <p>See the definition of
+ the <seealso marker="#type-handler_config">
+ <c>handler_config()</c></seealso> type for more
+ information about the different parameters.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="set_primary_config" arity="1"/>
+ <fsummary>Set primary configuration data for Logger.</fsummary>
+ <desc>
+ <p>Set primary configuration data for Logger. This
+ overwrites the current configuration.</p>
+ <p>To modify the existing configuration,
+ use <seealso marker="#update_primary_config-1">
+ <c>update_primary_config/1</c></seealso>, or, if a more
+ complex merge is needed, read the current configuration
+ with <seealso marker="#get_primary_config-0"><c>get_primary_config/0</c>
+ </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,
+ the default value is used.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="set_primary_config" arity="2" clause_i="1"/>
+ <name name="set_primary_config" arity="2" clause_i="2"/>
+ <name name="set_primary_config" arity="2" clause_i="3"/>
+ <fsummary>Add or update primary configuration data for Logger.</fsummary>
+ <type variable="Level" name_i="1"/>
+ <type variable="FilterDefault" name_i="2"/>
+ <type variable="Filters" name_i="3"/>
+ <desc>
+ <p>Add or update primary configuration data for Logger. If the
+ given <c><anno>Key</anno></c> already exists, its associated
+ value will be changed to the given value. If it does not
+ exist, it will be added.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="set_module_level" arity="2"/>
+ <fsummary>Set the log level for the specified modules.</fsummary>
+ <desc>
+ <p>Set the log level for the
+ specified modules.</p>
+ <p>The log level for a module overrides the primary log level
+ 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 primary 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 primary log level.</p>
+ <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 primary log level for Logger, use
+ <seealso marker="#set_primary_config/2">
+ <c>set_primary_config(level, Level)</c></seealso>.</p>
+ <p>To change the log level for a handler, use
+ <seealso marker="#set_handler_config/3">
+ <c>set_handler_config(HandlerId, level, Level)</c>
+ </seealso>.</p>
+ <note>
+ <p>The originating module for a log event is only detected
+ if the key <c>mfa</c> exists in the metadata, and is
+ associated with <c>{Module, Function, Arity}</c>. When log
+ macros are used, this association is 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 if module levels shall have any
+ effect.</p>
+ </note>
+ </desc>
+ </func>
+
+ <func>
+ <name name="set_process_metadata" arity="1"/>
+ <fsummary>Set metadata to use when logging from current process.</fsummary>
+ <desc>
+ <p>Set metadata which Logger shall automatically insert in
+ all log events produced on the current process.</p>
+ <p>Location data produced by the log macros, and/or metadata
+ given as argument to the log call (API function or macro),
+ are merged with the process metadata. If the same keys
+ occur, values from the metadata argument to the log call
+ overwrite values from the process metadata, which in turn
+ overwrite values from the location data.</p>
+ <p>Subsequent calls to this function overwrites previous data
+ set. To update existing data instead of overwriting it,
+ see <seealso marker="#update_process_metadata-1">
+ <c>update_process_metadata/1</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="unset_module_level" arity="0"/>
+ <fsummary>Remove module specific log settings for all modules.</fsummary>
+ <desc>
+ <p>Remove module specific log settings. After this, the
+ primary log level is used for all modules.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="unset_module_level" arity="1"/>
+ <fsummary>Remove module specific log settings for the given
+ modules.</fsummary>
+ <desc>
+ <p>Remove module specific log settings. After this, the
+ primary log level is used for the specified modules.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="unset_process_metadata" arity="0"/>
+ <fsummary>Delete data set with set_process_metadata/1.</fsummary>
+ <desc>
+ <p>Delete data set
+ with <seealso marker="#set_process_metadata-1">
+ <c>set_process_metadata/1</c></seealso> or
+ <seealso marker="#update_process_metadata-1">
+ <c>update_process_metadata/1</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="update_formatter_config" arity="2"/>
+ <fsummary>Update the formatter configuration for the specified handler.</fsummary>
+ <desc>
+ <p>Update the formatter configuration for the specified handler.</p>
+ <p>The new configuration is merged with the existing formatter
+ configuration.</p>
+ <p>To overwrite the existing configuration without any merge,
+ use</p>
+ <pre>
+<seealso marker="#set_handler_config-3">set_handler_config(HandlerId, formatter,
+ {FormatterModule, FormatterConfig})</seealso>.</pre>
+ </desc>
+ </func>
+
+ <func>
+ <name name="update_formatter_config" arity="3"/>
+ <fsummary>Update the formatter configuration for the specified handler.</fsummary>
+ <desc>
+ <p>Update the formatter configuration for the specified handler.</p>
+ <p>This is equivalent to</p>
+ <pre>
+<seealso marker="#update_formatter_config-2">update_formatter_config(<anno>HandlerId</anno>, #{<anno>Key</anno> => <anno>Value</anno>})</seealso></pre>
+ </desc>
+ </func>
+
+ <func>
+ <name name="update_handler_config" arity="2"/>
+ <fsummary>Update configuration data for the specified handler.</fsummary>
+ <desc>
+ <p>Update configuration data for the specified handler. This function
+ behaves as if it was implemented as follows:</p>
+ <code type="erl">
+{ok, {_, Old}} = logger:get_handler_config(HandlerId),
+logger:set_handler_config(HandlerId, maps:merge(Old, Config)).
+ </code>
+ <p>To overwrite the existing configuration without any merge,
+ use <seealso marker="#set_handler_config-2"><c>set_handler_config/2</c>
+ </seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="update_primary_config" arity="1"/>
+ <fsummary>Update primary configuration data for Logger.</fsummary>
+ <desc>
+ <p>Update primary configuration data for Logger. This function
+ behaves as if it was implemented as follows:</p>
+ <code type="erl">
+Old = logger:get_primary_config(),
+logger:set_primary_config(maps:merge(Old, Config)).
+ </code>
+ <p>To overwrite the existing configuration without any merge,
+ use <seealso marker="#set_primary_config-1"><c>set_primary_config/1</c>
+ </seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="update_process_metadata" arity="1"/>
+ <fsummary>Set or update metadata to use when logging from
+ current process.</fsummary>
+ <desc>
+ <p>Set or update metadata to use when logging from current
+ process</p>
+ <p>If process metadata exists for the current process, this
+ function behaves as if it was implemented as follows:</p>
+ <code type="erl">
+logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)).
+ </code>
+ <p>If no process metadata exists, the function behaves as
+ <seealso marker="#set_process_metadata-1">
+ <c>set_process_metadata/1</c>
+ </seealso>.</p>
+ </desc>
+ </func>
+ </funcs>
+
+ <section>
+ <marker id="misc_API"/>
+ <title>Miscellaneous API functions</title>
+ </section>
+ <funcs>
+ <func>
+ <name name="compare_levels" arity="2"/>
+ <fsummary>Compare the severity of two log levels.</fsummary>
+ <desc>
+ <p>Compare the severity of two log levels. Returns <c>gt</c>
+ if <c>Level1</c> is more severe than
+ <c>Level2</c>, <c>lt</c> if <c>Level1</c> is less severe,
+ and <c>eq</c> if the levels are equal.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="format_report" arity="1"/>
+ <fsummary>Convert a log message on report form to {Format, Args}.</fsummary>
+ <desc>
+ <p>Convert a log message on report form to <c>{Format,
+ Args}</c>. This is the default report callback used
+ by <seealso marker="logger_formatter">
+ <c>logger_formatter</c></seealso> when no custom report
+ callback is found. See
+ section <seealso marker="logger_chapter#log_message">Log
+ Message</seealso> in the Kernel User's Guide for
+ information about report callbacks and valid forms of log
+ messages.</p>
+ <p>The function produces lines of <c>Key: Value</c> from
+ key-value lists. Strings are printed with <c>~ts</c> and
+ other terms with <c>~tp</c>.</p>
+ <p>If <c><anno>Report</anno></c> is a map, it is converted to
+ a key-value list before formatting as such.</p>
+ </desc>
+ </func>
+ </funcs>
+
+ <section>
+ <marker id="handler_callback_functions"/>
+ <title>Handler Callback Functions</title>
+ <p>The following functions are to be exported from a handler
+ callback module.</p>
+ </section>
+
+ <funcs>
+ <func>
+ <name>HModule:adding_handler(Config1) -> {ok, Config2} | {error,
+ Reason}</name>
+ <fsummary>An instance of this handler is about to be added.</fsummary>
+ <type>
+ <v>Config1 = Config2 =
+ <seealso marker="#type-handler_config">handler_config()</seealso></v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>This callback function is optional.</p>
+ <p>The function is called on a temporary process when an new
+ handler is about to be added. The purpose is to verify the
+ configuration and initiate all resources needed by the
+ handler.</p>
+ <p>The handler identity is associated with the <c>id</c> key
+ in <c>Config1</c>.</p>
+ <p>If everything succeeds, the callback function can add
+ possible default values or internal state values to the
+ configuration, and return the adjusted map
+ in <c>{ok,Config2}</c>.</p>
+ <p>If the configuration is faulty, or if the initiation fails,
+ the callback function must return <c>{error,Reason}</c>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>HModule:changing_config(Config1, Config2) -> {ok, Config3} | {error, Reason}</name>
+ <fsummary>The configuration for this handler is about to change.</fsummary>
+ <type>
+ <v>Config1 = Config2 = Config3 =
+ <seealso marker="#type-handler_config">handler_config()</seealso></v>
+ <v>Reason = term()</v>
+ </type>
+ <desc>
+ <p>This callback function is optional.</p>
+ <p>The function is called on a temporary process when the
+ configuration for a handler is about to change. The purpose
+ is to verify and act on the new configuration.</p>
+ <p><c>Config1</c> is the existing configuration
+ and <c>Config2</c> is the new configuration.</p>
+ <p>The handler identity is associated with the <c>id</c> key
+ in <c>Config1</c>.</p>
+ <p>If everything succeeds, the callback function must return a
+ possibly adjusted configuration in <c>{ok,Config3}</c>.</p>
+ <p>If the configuration is faulty, the callback function must
+ return <c>{error,Reason}</c>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>HModule:log(LogEvent, Config) -> void()</name>
+ <fsummary>Log the given log event.</fsummary>
+ <type>
+ <v>LogEvent =
+ <seealso marker="#type-log_event">log_event()</seealso></v>
+ <v>Config =
+ <seealso marker="#type-handler_config">handler_config()</seealso></v>
+ </type>
+ <desc>
+ <p>This callback function is mandatory.</p>
+ <p>The function is called when all primary filters and all
+ handler filters for the handler in question have passed for
+ the given log event. It is called on the client process, that
+ is, the process that issued the log event.</p>
+ <p>The handler identity is associated with the <c>id</c> key
+ in <c>Config</c>.</p>
+ <p>The handler must log the event.</p>
+ <p>The return value from this function is ignored by
+ Logger.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name>HModule:removing_handler(Config) -> ok</name>
+ <fsummary>The given handler is about to be removed.</fsummary>
+ <type>
+ <v>Config =
+ <seealso marker="#type-handler_config">handler_config()</seealso></v>
+ </type>
+ <desc>
+ <p>This callback function is optional.</p>
+ <p>The function is called on a temporary process when a
+ handler is about to be removed. The purpose is to release
+ all resources used by the handler.</p>
+ <p>The handler identity is associated with the <c>id</c> key
+ in <c>Config</c>.</p>
+ <p>The return value is ignored by Logger.</p>
+ </desc>
+ </func>
+
+ </funcs>
+
+ <section>
+ <marker id="formatter_callback_functions"/>
+ <title>Formatter Callback Functions</title>
+ <p>The following functions are to be exported from a formatter
+ callback module.</p>
+ </section>
+
+ <funcs>
+ <func>
+ <name>FModule:check_config(FConfig) -> ok | {error, Reason}</name>
+ <fsummary>Validate the given formatter configuration.</fsummary>
+ <type>
+ <v>FConfig =
+ <seealso marker="#type-formatter_config">formatter_config()</seealso></v>
+ <v>Reason = term()</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,Reason}</c> if it is faulty.</p>
+ <p>The following Logger API functions can trigger this callback:</p>
+ <list>
+ <item><seealso marker="logger#add_handler-3">
+ <c>logger:add_handler/3</c></seealso></item>
+ <item><seealso marker="logger#set_handler_config-2">
+ <c>logger:set_handler_config/2,3</c></seealso></item>
+ <item><seealso marker="logger#update_handler_config-2">
+ <c>logger:updata_handler_config/2</c></seealso></item>
+ <item><seealso marker="logger#update_formatter_config-2">
+ <c>logger:update_formatter_config/2</c></seealso></item>
+ </list>
+ <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>
+ <v>LogEvent =
+ <seealso marker="#type-log_event">log_event()</seealso></v>
+ <v>FConfig =
+ <seealso marker="#type-formatter_config">formatter_config()</seealso></v>
+ <v>FormattedLogEntry =
+ <seealso marker="unicode#type-chardata">unicode:chardata()</seealso></v>
+ </type>
+ <desc>
+ <p>This callback function is mandatory.</p>
+ <p>The function can be called by a log handler to convert a
+ log event term to a printable string. The returned value
+ can, for example, be printed as a log entry to the console
+ or a file using <seealso marker="stdlib:io#put_chars-1">
+ <c>io:put_chars/1,2</c></seealso>.</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>
+ </funcs>
+
+ <section>
+ <title>See Also</title>
+ <p>
+ <seealso marker="config"><c>config(4)</c></seealso>,
+ <seealso marker="erts:erlang"><c>erlang(3)</c></seealso>,
+ <seealso marker="stdlib:io"><c>io(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="stdlib:unicode"><c>unicode(3)</c></seealso>
+ </p>
+ </section>
+</erlref>
+
+
diff --git a/lib/kernel/doc/src/logger_arch.dia b/lib/kernel/doc/src/logger_arch.dia
new file mode 100644
index 0000000000..97be31856e
--- /dev/null
+++ b/lib/kernel/doc/src/logger_arch.dia
Binary files differ
diff --git a/lib/kernel/doc/src/logger_arch.png b/lib/kernel/doc/src/logger_arch.png
new file mode 100644
index 0000000000..70933a5a41
--- /dev/null
+++ b/lib/kernel/doc/src/logger_arch.png
Binary files differ
diff --git a/lib/kernel/doc/src/logger_chapter.xml b/lib/kernel/doc/src/logger_chapter.xml
new file mode 100644
index 0000000000..30172f6ca6
--- /dev/null
+++ b/lib/kernel/doc/src/logger_chapter.xml
@@ -0,0 +1,1331 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2017</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>Logging</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ <file>logger_chapter.xml</file>
+ </header>
+
+ <p>Erlang/OTP 21.0 provides a 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
+ formatters can be plugged in.</p>
+ <p>By default, the Kernel application installs one log handler at
+ system start. This handler is named <c>default</c>. It receives
+ and processes standard log events produced by the Erlang runtime
+ system, standard behaviours and different Erlang/OTP
+ applications. The log events are by default written to the
+ terminal.</p>
+ <p>You can also configure the system so that the default handler
+ prints log events to a single file, or to a set of wrap logs
+ via <seealso marker="disk_log"><c>disk_log</c></seealso>.</p>
+ <p>By configuration, you can also modify or disable the default
+ handler, replace it by a custom handler, and install additional
+ handlers.</p>
+
+ <note>
+ <p>Since Logger is new in Erlang/OTP 21.0, we do reserve the right
+ to introduce changes to the Logger API and functionality in
+ patches following this release. These changes might or might not
+ be backwards compatible with the initial version.</p>
+ </note>
+
+ <section>
+ <title>Overview</title>
+ <p>A <em>log event</em> consists of a <em>log level</em>, the
+ <em>message</em> to be logged, and <em>metadata</em>.</p>
+ <p>The Logger backend forwards log events from the API, first
+ through a set of <em>primary filters</em>, then through a set of
+ secondary filters attached to each log handler. The secondary
+ filters are in the following named <em>handler filters</em>.</p>
+ <p>Each filter set consists of a <em>log level check</em>,
+ followed by zero or more <em>filter functions</em>.</p>
+ <p>The following figure shows a conceptual overview of Logger. The
+ figure shows two log handlers, but any number of handlers can be
+ installed.</p>
+
+ <!-- The image is edited with dia in logger_arch.dia file,
+ and .png file generated with make target 'png'. -->
+ <image file="logger_arch.png">
+ <icaption>Conceptual Overview</icaption>
+ </image>
+
+ <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 passes 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 primary 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>
+ <p>Filter functions can be used for more sophisticated filtering
+ than the log level check provides. A filter function can stop or
+ pass a log event, based on any of the event's contents. It can
+ also modify all parts of the log event. See see
+ section <seealso marker="#filters">Filters</seealso> for more
+ details.</p>
+ <p>If a log event passes through all primary filters and all
+ handler filters for a specific handler, Logger forwards the
+ event to the <em>handler callback</em>. The handler formats and
+ prints the event to its destination. See
+ section <seealso marker="#handlers">Handlers</seealso> for more
+ details.</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>
+ <marker id="logger_api"/>
+ <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 primary 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,
+ <url href="https://www.ietf.org/rfc/rfc5424.txt">RFC
+ 5424</url>, 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 conditions</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 <em>report callback</em> 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, or
+ directly to a string. The
+ formatter can also use its own conversion function, if no
+ callback is provided, or if a customized formatting is
+ desired.</p>
+ <p>The report callback must be a fun with one or two
+ arguments. If it takes one argument, this is the report
+ itself, and the fun returns a format string and arguments:</p>
+ <pre>fun((<seealso marker="logger#type-report"><c>logger:report()</c></seealso>) -> {<seealso marker="stdlib:io#type-format"><c>io:format()</c></seealso>,[term()]})</pre>
+ <p>If it takes two arguments, the first is the report, and the
+ second is a map containing extra data that allows direct
+ coversion to a string:</p>
+ <pre>fun((<seealso marker="logger#type-report"><c>logger:report()</c></seealso>,<seealso marker="logger#type-report_cb_config"><c>logger:report_cb_config()</c></seealso>) -> <seealso marker="stdlib:unicode#type-chardata"><c>unicode:chardata()</c></seealso>)
+ </pre>
+ <p>The fun must obey the <c>encoding</c>, <c>depth</c>
+ and <c>chars_limit</c> parameters provided in the second
+ argument, as the formatter can not do anything useful of these
+ parameters with the returned string. This variant is used when
+ the formatting of the report depends on the size and encoding
+ parameters.</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 primary 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 specific log event</tag>
+ <item>
+ <p>Metadata associated with one specific 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 primary, or attached to a specific
+ handler. Logger calls the primary filters first, and if they all
+ pass, it calls the handler filters for each handler. Logger
+ calls the handler callback only if all filters attached to the
+ handler in question also pass.</p>
+ <p>A filter is defined as:</p>
+ <pre>{FilterFun, Extra}</pre>
+ <p>where <c>FilterFun</c> is a function of arity 2,
+ and <c>Extra</c> is any term. When applying the filter, Logger
+ calls the function with the log event as the first argument,
+ and the value of <c>Extra</c> as the second
+ argument. See <seealso marker="logger#type-filter">
+ <c>logger:filter()</c></seealso> for type definitions.</p>
+ <p>The filter function can return <c>stop</c>, <c>ignore</c> or
+ the (possibly modified) log event.</p>
+ <p>If <c>stop</c> is returned, the log event is immediately
+ discarded. If the filter is primary, 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 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 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
+ filters to decide the event's destiny.</p>
+ <p>The configuration option <c>filter_default</c> specifies the
+ behaviour if all filter functions 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>Primary filters are added
+ with <seealso marker="logger#add_primary_filter-2">
+ <c>logger:add_primary_filter/2</c></seealso>
+ and removed
+ with <seealso marker="logger#remove_primary_filter-1">
+ <c>logger:remove_primary_filter/1</c></seealso>. They can also
+ be added at system start via the Kernel configuration
+ parameter <seealso marker="#logger_parameter"><c>logger</c></seealso>.</p>
+ <p>Handler filters are added
+ with <seealso marker="logger#add_handler_filter-3">
+ <c>logger:add_handler_filter/3</c></seealso>
+ and removed
+ with <seealso marker="logger#remove_handler_filter-2">
+ <c>logger:remove_handler_filter/2</c></seealso>. They can also
+ 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 the Kernel configuration
+ parameter <seealso marker="#logger_parameter"><c>logger</c></seealso>.</p>
+
+ <p>To see which filters are currently installed in the system,
+ use <seealso marker="logger#get_config-0">
+ <c>logger:get_config/0</c></seealso>,
+ or <seealso marker="logger#get_primary_config-0">
+ <c>logger:get_primary_config/0</c></seealso>
+ and <seealso marker="logger#get_handler_config-1">
+ <c>logger:get_handler_config/1</c></seealso>. Filters are
+ 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>
+
+ <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>
+ <marker id="handlers"/>
+ <title>Handlers</title>
+ <p>A handler is defined as a module exporting at least the
+ following callback function:</p>
+
+ <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
+ primary 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 involved or not.</p>
+
+ <p>Logger allows adding multiple instances of a handler
+ 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
+ functions <c>adding_handler/1</c>, <c>changing_config/2</c>
+ and <c>removing_handler/1</c>. See
+ section <seealso marker="logger#handler_callback_functions">Handler
+ Callback Functions</seealso> in the logger(3) manual page for
+ more information about these function.</p>
+
+ <p>The following built-in handlers exist:</p>
+
+ <taglist>
+ <tag><c>logger_std_h</c></tag>
+ <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, terminal or file.</p>
+ </item>
+
+ <tag><c>logger_disk_log_h</c></tag>
+ <item>
+ <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 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
+ with <seealso marker="error_logger#add_report_handler-1">
+ <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 21.0
+ or later.</p>
+ </item>
+ </taglist>
+ </section>
+
+ <section>
+ <marker id="formatters"/>
+ <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 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 consist of a formatter
+ module, <c>FModule</c> and its
+ configuration, <c>FConfig</c>. <c>FModule</c> must export the
+ following function, which can be called by the handler:</p>
+ <pre><seealso marker="logger#FModule:format-2">format(LogEvent,FConfig)
+ -> FormattedLogEntry</seealso></pre>
+ <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 <c>logger_formatter</c> as default. See
+ the <seealso marker="logger_formatter"><c>logger_formatter(3)</c></seealso>
+ manual page for more information about this module.</p>
+ </section>
+
+ <section>
+ <title>Configuration</title>
+
+ <p>At system start, Logger is configured through Kernel
+ configuration parameters. The parameters that apply to Logger
+ are described in
+ section <seealso marker="#kernel_config_params">Kernel
+ Configuration Parameters</seealso>. Examples are found in
+ section <seealso marker="#config_examples">Configuration
+ Examples</seealso>.</p>
+ <p>During runtime, Logger configuration is changed via API
+ functions. See
+ section <seealso marker="logger#configuration_API">Configuration
+ API Functions</seealso> in the <c>logger(3)</c> manual page.</p>
+
+ <section>
+ <title>Primary Logger Configuration</title>
+ <p>Logger API functions that apply to the primary Logger
+ configuration are:</p>
+ <list>
+ <item><seealso marker="logger#get_primary_config-0">
+ <c>get_primary_config/0</c></seealso></item>
+ <item><seealso marker="logger#set_primary_config-1">
+ <c>set_primary_config/1,2</c></seealso></item>
+ <item><seealso marker="logger#update_primary_config-1">
+ <c>update_primary_config/1</c></seealso></item>
+ <item><seealso marker="logger#add_primary_filter-2">
+ <c>add_primary_filter/2</c></seealso></item>
+ <item><seealso marker="logger#remove_primary_filter-1">
+ <c>remove_primary_filter/1</c></seealso></item>
+ </list>
+ <p>The primary Logger configuration is a map with the following
+ keys:</p>
+ <taglist>
+ <tag><marker id="primary_level"/>
+ <c>level = </c><seealso marker="logger#type-level">
+ <c>logger:level()</c></seealso><c> | all | none</c></tag>
+ <item>
+ <p>Specifies the primary log level, that is, log event that
+ are equally or more severe than this level, are forwarded
+ to the primary filters. Less severe log events are
+ immediately discarded.</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="#logger_level">
+ <c>logger_level</c></seealso>. It is changed during
+ runtime with <seealso marker="logger#set_primary_config-2">
+ <c>logger:set_primary_config(level,Level)</c></seealso>.</p>
+ <p>Defaults to <c>info</c>.</p>
+ </item>
+ <tag><c>filters = [{FilterId,Filter}]</c></tag>
+ <item>
+ <p>Specifies the primary filters.</p>
+ <list>
+ <item><c>FilterId = </c><seealso marker="logger#type-filter_id">
+ <c>logger:filter_id()</c></seealso></item>
+ <item><c>Filter = </c><seealso marker="logger#type-filter">
+ <c>logger:filter()</c></seealso></item>
+ </list>
+ <p>The initial value of this option is set by the Kernel
+ configuration
+ parameter <seealso marker="#logger_parameter"><c>logger</c></seealso>.
+ During runtime, primary filters are added and removed with
+ <seealso marker="logger#add_primary_filter-2">
+ <c>logger:add_primary_filter/2</c></seealso> and
+ <seealso marker="logger#remove_primary_filter-1">
+ <c>logger:remove_primary_filter/1</c></seealso>,
+ respectively.</p>
+ <p>See section <seealso marker="#filters">Filters</seealso>
+ for more detailed information.</p>
+ <p>Defaults to <c>[]</c>.</p>
+ </item>
+ <tag><c>filter_default = log | stop</c></tag>
+ <item>
+ <p>Specifies what happens to a log event if all filters
+ 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>Defaults to <c>log</c>.</p>
+ </item>
+ </taglist>
+ </section>
+
+ <section>
+ <marker id="handler_configuration"/>
+ <title>Handler Configuration</title>
+ <p>Logger API functions that apply to handler configuration
+ are:</p>
+ <list>
+ <item><seealso marker="logger#get_handler_config-0">
+ <c>get_handler_config/0,1</c></seealso></item>
+ <item><seealso marker="logger#set_handler_config-2">
+ <c>set_handler_config/2,3</c></seealso></item>
+ <item><seealso marker="logger#update_handler_config-2">
+ <c>update_handler_config/2</c></seealso></item>
+ <item><seealso marker="logger#add_handler_filter-3">
+ <c>add_handler_filter/3</c></seealso></item>
+ <item><seealso marker="logger#remove_handler_filter-2">
+ <c>remove_handler_filter/2</c></seealso></item>
+ <item><seealso marker="logger#update_formatter_config-2">
+ <c>update_formatter_config/2,3</c></seealso></item>
+ </list>
+ <p>The configuration for a handler is a map with the following keys:</p>
+ <taglist>
+ <tag><c>id = </c><seealso marker="logger#type-handler_id">
+ <c>logger:handler_id()</c></seealso></tag>
+ <item>
+ <p>Automatically inserted by Logger. The value is the same
+ as the <c>HandlerId</c> specified when adding the handler,
+ and it cannot be changed.</p>
+ </item>
+ <tag><c>module = module()</c></tag>
+ <item>
+ <p>Automatically inserted by Logger. The value is the same
+ as the <c>Module</c> specified when adding the handler,
+ and it cannot be changed.</p>
+ </item>
+ <tag><c>level = </c><seealso marker="logger#type-level">
+ <c>logger:level()</c></seealso><c> | all | none</c></tag>
+ <item>
+ <p>Specifies the log level for the handler, that is, log
+ events that are equally or more severe than this level,
+ are forwarded to the handler filters for this
+ handler.</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 is specified when adding the handler, or
+ changed during runtime with, for
+ instance, <seealso marker="logger#set_handler_config/3">
+ <c>logger:set_handler_config(HandlerId,level,Level)</c></seealso>.
+ </p>
+ <p>Defaults to <c>all</c>.</p>
+ </item>
+ <tag><c>filters = [{FilterId,Filter}]</c></tag>
+ <item>
+ <p>Specifies the handler filters.</p>
+ <list>
+ <item><c>FilterId = </c><seealso marker="logger#type-filter_id">
+ <c>logger:filter_id()</c></seealso></item>
+ <item><c>Filter = </c><seealso marker="logger#type-filter">
+ <c>logger:filter()</c></seealso></item>
+ </list>
+ <p>Handler filters are specified when adding the handler,
+ or added or removed during runtime with
+ <seealso marker="logger#add_handler_filter-3">
+ <c>logger:add_handler_filter/3</c></seealso> and
+ <seealso marker="logger#remove_handler_filter-2">
+ <c>logger:remove_handler_filter/2</c></seealso>,
+ respectively.</p>
+ <p>See <seealso marker="#filters">Filters</seealso> for more
+ detailed information.</p>
+ <p>Defaults to <c>[]</c>.</p>
+ </item>
+ <tag><c>filter_default = log | stop</c></tag>
+ <item>
+ <p>Specifies what happens to a log event if all filters
+ 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>Defaults to <c>log</c>.</p>
+ </item>
+ <tag><c>formatter = {FormatterModule,FormatterConfig}</c></tag>
+ <item>
+ <p>Specifies a formatter that the handler can use for
+ converting the log event term to a printable string.</p>
+ <list>
+ <item><c>FormatterModule = module()</c></item>
+ <item><c>FormatterConfig = </c>
+ <seealso marker="logger#type-formatter_config">
+ <c>logger:formatter_config()</c></seealso></item>
+ </list>
+ <p>The formatter information is specified when adding the
+ handler. The formatter configuration can be changed during
+ runtime
+ with <seealso marker="logger#update_formatter_config-2">
+ <c>logger:update_formatter_config/2,3</c></seealso>,
+ or the complete formatter information can be overwritten
+ with, for
+ instance, <seealso marker="logger#set_handler_config-3">
+ <c>logger:set_handler_config/3</c></seealso>.</p>
+ <p>See
+ section <seealso marker="#formatters">Formatters</seealso>
+ for more detailed information.</p>
+ <p>Defaults
+ to <c>{logger_formatter,DefaultFormatterConfig}</c>. See
+ the <seealso marker="logger_formatter">
+ <c>logger_formatter(3)</c></seealso> manual page for
+ information about this formatter and its default
+ configuration.</p>
+ </item>
+ <tag><c>config = term()</c></tag>
+ <item>
+ <p>Handler specific configuration, that is, configuration
+ data related to a specific handler implementation.</p>
+ <p>The configuration for the built-in handlers is described
+ in
+ the <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> manual pages.</p>
+ </item>
+ </taglist>
+
+ <p>Notice that <c>level</c> and <c>filters</c> are obeyed by
+ Logger itself before forwarding the log events to each
+ handler, while <c>formatter</c> and all handler specific
+ options are left to the handler implementation.</p>
+ </section>
+
+ <section>
+ <marker id="kernel_config_params"/>
+ <title>Kernel Configuration Parameters</title>
+
+ <p>The following Kernel configuration parameters apply to
+ Logger:</p>
+ <taglist>
+ <tag><marker id="logger_parameter"/><c>logger = [Config]</c></tag>
+ <item>
+ <p>Specifies the configuration
+ for <seealso marker="logger">Logger</seealso>, except the
+ primary log level, which is specified
+ with <seealso marker="#logger_level"><c>logger_level</c></seealso>,
+ and the compatibility
+ with <seealso marker="sasl:error_logging">SASL Error
+ Logging</seealso>, which is specified
+ with <seealso marker="#logger_sasl_compatible">
+ <c>logger_sasl_compatible</c></seealso>.</p>
+ <p>With this parameter, you can modify or disable the default
+ handler, add custom handlers and primary logger filters, and
+ set log levels per module.</p>
+ <p><c>Config</c> is any (zero or more) of the following:</p>
+ <taglist>
+ <tag><c>{handler, default, undefined}</c></tag>
+ <item>
+ <p>Disables the default handler. This allows another
+ application to add its own default handler.</p>
+ <p>Only one entry of this type is allowed.</p>
+ </item>
+ <tag><c>{handler, HandlerId, Module, HandlerConfig}</c></tag>
+ <item>
+ <p>If <c>HandlerId</c> is <c>default</c>, then this entry
+ modifies the default handler, equivalent to calling</p>
+ <pre><seealso marker="logger#set_handler_config-2">
+ logger:set_handler_config(default, Module, HandlerConfig)
+ </seealso></pre>
+ <p>For all other values of <c>HandlerId</c>, this entry
+ adds a new handler, equivalent to calling</p>
+ <pre><seealso marker="logger:add_handler/3">
+ logger:add_handler(HandlerId, Module, HandlerConfig)
+ </seealso></pre>
+ <p>Multiple entries of this type are allowed.</p></item>
+ <tag><c>{filters, FilterDefault, [Filter]}</c></tag>
+ <item>
+ <p>Adds the specified primary filters.</p>
+ <list>
+ <item><c>FilterDefault = log | stop</c></item>
+ <item><c>Filter = {FilterId, {FilterFun, FilterConfig}}</c></item>
+ </list>
+ <p>Equivalent to calling</p>
+ <pre><seealso marker="logger#add_primary_filter/2">
+ logger:add_primary_filter(FilterId, {FilterFun, FilterConfig})
+ </seealso></pre>
+ <p>for each <c>Filter</c>.</p>
+ <p><c>FilterDefault</c> specifies the behaviour if all
+ primary filters return <c>ignore</c>, see
+ section <seealso marker="#filters">Filters</seealso>.</p>
+ <p>Only one entry of this type is allowed.</p>
+ </item>
+ <tag><c>{module_level, Level, [Module]}</c></tag>
+ <item>
+ <p>Sets module log level for the given modules. Equivalent
+ to calling</p>
+ <pre><seealso marker="logger#set_module_level/2">
+ logger:set_module_level(Module, Level)</seealso></pre>
+ <p>for each <c>Module</c>.</p>
+ <p>Multiple entries of this type are allowed.</p>
+ </item>
+ </taglist>
+ <p>See
+ section <seealso marker="#config_examples">Configuration
+ Examples</seealso> for examples using the <c>logger</c>
+ parameter for system configuration.</p>
+ </item>
+ <tag><marker id="logger_level"/>
+ <c>logger_level = Level</c></tag>
+ <item>
+ <p>Specifies the primary log level. See
+ the <seealso marker="kernel_app#logger_level"><c>kernel(6)</c></seealso>
+ manual page for more information about this parameter.</p>
+ </item>
+ <tag><marker id="logger_sasl_compatible"/>
+ <c>logger_sasl_compatible = true | false</c></tag>
+ <item>
+ <p>Specifies Logger's compatibility
+ with <seealso marker="sasl:error_logging">SASL Error
+ Logging</seealso>. See
+ the <seealso marker="kernel_app#logger_sasl_compatible">
+ <c>kernel(6)</c></seealso> manual page for more
+ information about this parameter.</p>
+ </item>
+ </taglist>
+ </section>
+
+ <section>
+ <marker id="config_examples"/>
+ <title>Configuration Examples</title>
+ <p>The value of the Kernel configuration parameter <c>logger</c>
+ is a list of tuples. It is possible to write the term on the
+ command line when starting an erlang node, but as the term
+ grows, a better approach is to use the system configuration
+ file. See
+ the <seealso marker="config"><c>config(4)</c></seealso> manual
+ page for more information about this file.</p>
+ <p>Each of the following examples shows a simple system
+ configuration file that configures Logger according to the
+ description.</p>
+ <p>Modify the default handler to print to a file instead of
+ <c>standard_io</c>:</p>
+ <code>
+[{kernel,
+ [{logger,
+ [{handler, default, logger_std_h, % {handler, HandlerId, Module,
+ #{config => #{type => {file,"log/erlang.log"}}}} % Config}
+ ]}]}].
+ </code>
+ <p>Modify the default handler to print each log event as a
+ single line:</p>
+ <code>
+[{kernel,
+ [{logger,
+ [{handler, default, logger_std_h,
+ #{formatter => {logger_formatter, #{single_line => true}}}}
+ ]}]}].
+ </code>
+ <p>Modify the default handler to print the pid of the logging
+ process for each log event:</p>
+ <code>
+[{kernel,
+ [{logger,
+ [{handler, default, logger_std_h,
+ #{formatter => {logger_formatter,
+ #{template => [time," ",pid," ",msg,"\n"]}}}}
+ ]}]}].
+ </code>
+ <p>Modify the default handler to only print errors and more
+ severe log events to "log/erlang.log", and add another handler
+ to print all log events to "log/debug.log".</p>
+ <code>
+[{kernel,
+ [{logger,
+ [{handler, default, logger_std_h,
+ #{level => error,
+ config => #{type => {file, "log/erlang.log"}}}},
+ {handler, info, logger_std_h,
+ #{level => debug,
+ config => #{type => {file, "log/debug.log"}}}}
+ ]}]}].
+ </code>
+ </section>
+
+ </section>
+
+ <section>
+ <marker id="compatibility"/>
+ <title>Backwards Compatibility with error_logger</title>
+ <p>Logger provides backwards compatibility with
+ <c>error_logger</c> in the following ways:</p>
+
+ <taglist>
+ <tag>API for Logging</tag>
+ <item>
+ <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">
+ <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>
+ <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>,
+ use the default formatter, <c>logger_formatter</c>, with
+ configuration parameter <c>legacy_header</c> set
+ to <c>true</c>. This is the default configuration of
+ the <c>default</c> handler started by Kernel.</p>
+ </item>
+ <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><marker id="sasl_reports"/>SASL Reports</tag>
+ <item>
+ <p>By SASL reports we mean supervisor reports, crash reports
+ and progress reports.</p>
+ <p>Prior to Erlang/OTP 21.0, these reports were only logged
+ when the SASL application was running, and they were printed
+ trough SASL's own event handlers <c>sasl_report_tty_h</c>
+ and <c>sasl_report_file_h</c>.</p>
+ <p>The destination of these log events was configured by
+ <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 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
+ are no longer connected to the SASL application.</item>
+ <item>Supervisor reports and crash reports are issued
+ as <c>error</c> level log events, and are logged through
+ the default handler started by Kernel.</item>
+ <item>Progress reports are issued as <c>info</c> level log
+ events, and since the default primary log level
+ is <c>notice</c>, these are not logged by default. To
+ enable printing of progress reports, set
+ the <seealso marker="#primary_level">primary log
+ level</seealso> to <c>info</c>.</item>
+ <item>The output format is the same for all log
+ events.</item>
+ </list>
+ <p>If the old behaviour is preferred, the Kernel configuration
+ parameter <seealso marker="kernel_app#logger_sasl_compatible">
+ <c>logger_sasl_compatible</c></seealso> can be set
+ to <c>true</c>. The
+ <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</c> which
+ is set to <c>[otp,sasl]</c>. This field can be
+ used by filters to stop or allow the log events.</p>
+ <p>See section <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 automatically starts the error logger event manager,
+ and adds <c>error_logger</c> as a handler to Logger, with
+ the following configuration:</p>
+<code>
+#{level => info,
+ filter_default => log,
+ filters => []}.
+</code>
+ <note>
+ <p>This handler ignores events that do not 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>The handler is not overload protected.</p>
+ </note>
+ </item>
+ </taglist>
+ </section>
+
+
+ <section>
+ <title>Error Handling</title>
+ <p>Logger does, to a certain extent, check its input data before
+ forwarding a log event to filters and handlers. It does,
+ however, not evaluate report callbacks, or check the validity of
+ format strings and arguments. This means that all filters and
+ handlers 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
+ 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.</p>
+ <p>See section <seealso marker="#log_message">Log
+ Message</seealso> for more information about report callbacks
+ and valid forms of log messages.</p>
+ </section>
+
+ <section>
+ <title>Example: Add a handler to log info events to file</title>
+ <p>When starting an Erlang node, the default behaviour is that all
+ log events on level <c>notice</c> or more severe, are logged to
+ the terminal via the default handler. To also log info events,
+ you can either change the primary log level to <c>info</c>:</p>
+ <pre>
+1> <input>logger:set_primary_config(level, info).</input>
+ok</pre>
+ <p>or set the level for one or a few modules only:</p>
+ <pre>
+2> <input>logger:set_module_level(mymodule, info).</input>
+ok</pre>
+ <p>This allows info events to pass through to the default handler,
+ and be printed to the terminal as well. If there are many info
+ events, it can be useful to print these to a file instead.</p>
+ <p>First, set the log level of the default handler
+ to <c>notice</c>, preventing it from printing info events to the
+ terminal:</p>
+ <pre>
+3> <input>logger:set_handler_config(default, level, notice).</input>
+ok</pre>
+ <p>Then, add a new handler which prints to file. You can use the
+ handler
+ module <seealso marker="logger_std_h"><c>logger_std_h</c></seealso>,
+ and specify type <c>{file,File}</c>.:</p>
+ <pre>
+4> <input>Config = #{config => #{type => {file,"./info.log"}}, level => info}.</input>
+#{config => #{type => {file,"./info.log"}},level => info}
+5> <input>logger:add_handler(myhandler, logger_std_h, Config).</input>
+ok</pre>
+ <p>Since <c>filter_default</c> defaults to <c>log</c>, this
+ handler now receives all log events. If you want info events
+ only in the file, you must add a filter to stop all non-info
+ events. The built-in
+ filter <seealso marker="logger_filters#level-2">
+ <c>logger_filters:level/2</c></seealso>
+ can do this:</p>
+ <pre>
+6> <input>logger:add_handler_filter(myhandler, stop_non_info,
+ {fun logger_filters:level/2, {stop, neq, info}}).</input>
+ok</pre>
+ <p>See section <seealso marker="#filters">Filters</seealso> for
+ more information about the filters and the <c>filter_default</c>
+ configuration parameter.</p>
+
+ </section>
+
+ <section>
+ <title>Example: Implement a handler</title>
+ <p>Section <seealso marker="logger#handler_callback_functions">Handler
+ Callback Functions</seealso> in the logger(3) manual page
+ describes the callback functions that can be implemented for a
+ Logger handler.</p>
+ <p>A handler callback module must export:</p>
+ <list>
+ <item><c>log(Log, Config)</c></item>
+ </list>
+ <p>It can optionally also export some, or all, of the following:</p>
+ <list>
+ <item><c>adding_handler(Config)</c></item>
+ <item><c>removing_handler(Config)</c></item>
+ <item><c>changing_config(OldConfig, NewConfig)</c></item>
+ </list>
+ <p>When a handler is added, by for example a call
+ to <seealso marker="logger#add_handler-3">
+ <c>logger:add_handler(Id, HModule, Config)</c></seealso>,
+ Logger first calls <c>HModule:adding_handler(Config)</c>. If
+ this function returns <c>{ok,Config1}</c>, Logger
+ writes <c>Config1</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
+ <seealso marker="logger#remove_handler-1">
+ <c>logger:remove_handler(Id)</c></seealso>. Logger calls
+ <c>HModule:removing_handler(Config)</c>, and removes the
+ handler's configuration from the configuration database.</p>
+ <p>When <seealso marker="logger#set_handler_config-2">
+ <c>logger:set_handler_config/2,3</c></seealso>
+ or <seealso marker="logger#update_handler_config/2">
+ <c>logger:update_handler_config/2</c></seealso> is called,
+ Logger
+ calls <c>HModule:changing_config(OldConfig, NewConfig)</c>. If
+ this function returns <c>{ok,NewConfig1}</c>, Logger
+ writes <c>NewConfig1</c> to the configuration database.</p>
+
+ <p>A simple handler that prints to the terminal can be implemented
+ as follows:</p>
+ <code>
+-module(myhandler1).
+-export([log/2]).
+
+log(LogEvent, #{formatter := {FModule, FConfig}}) ->
+ io:put_chars(FModule:format(LogEvent, FConfig)).
+ </code>
+
+ <p>Notice that the above handler does not have any overload
+ protection, and all log events are printed directly from the
+ client process.</p>
+ <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</c></seealso>
+ and <seealso marker="logger_disk_log_h"><c>logger_disk_log_h</c>
+ </seealso>.</p>
+ <p>The following is a simpler example of a handler which logs to a
+ file through one single process:</p>
+ <code>
+-module(myhandler2).
+-export([adding_handler/1, removing_handler/1, log/2]).
+-export([init/1, handle_call/3, handle_cast/2, terminate/2]).
+
+adding_handler(Config) ->
+ MyConfig = maps:get(config,Config,#{file => "myhandler2.log"}),
+ {ok, Pid} = gen_server:start(?MODULE, MyConfig, []),
+ {ok, Config#{config => MyConfig#{pid => Pid}}}.
+
+removing_handler(#{config := #{pid := Pid}}) ->
+ gen_server:stop(Pid).
+
+log(LogEvent,#{config := #{pid := Pid}} = Config) ->
+ gen_server:cast(Pid, {log, LogEvent, Config}).
+
+init(#{file := File}) ->
+ {ok, Fd} = file:open(File, [append, {encoding, utf8}]),
+ {ok, #{file => File, fd => Fd}}.
+
+handle_call(_, _, State) ->
+ {reply, {error, bad_request}, State}.
+
+handle_cast({log, LogEvent, Config}, #{fd := Fd} = State) ->
+ do_log(Fd, LogEvent, Config),
+ {noreply, State}.
+
+terminate(_Reason, #{fd := Fd}) ->
+ _ = file:close(Fd),
+ ok.
+
+do_log(Fd, LogEvent, #{formatter := {FModule, FConfig}}) ->
+ String = FModule:format(LogEvent, FConfig),
+ io:put_chars(Fd, String).
+ </code>
+ </section>
+
+ <section>
+ <marker id="overload_protection"/>
+ <title>Protecting the Handler from Overload</title>
+ <p>The default handlers, <seealso marker="logger_std_h">
+ <c>logger_std_h</c></seealso> and <seealso marker="logger_disk_log_h">
+ <c>logger_disk_log_h</c></seealso>, feature an overload protection
+ mechanism, which makes it possible for the handlers to survive,
+ and stay responsive, during periods of high load (when huge
+ numbers of incoming log requests must be handled).
+ The mechanism works as follows:</p>
+
+ <section>
+ <title>Message Queue Length</title>
+ <p>The handler process keeps track of the length of its message
+ queue and takes some form of action when the current length exceeds a
+ configurable threshold. The purpose is to keep the handler in, or to
+ as quickly as possible get the handler into, a state where it can
+ keep up with the pace of incoming log events. The memory use of the
+ handler must never grow larger and larger, since that will eventually
+ cause the handler to crash. These three thresholds, with associated
+ actions, exist:</p>
+
+ <taglist>
+ <tag><c>sync_mode_qlen</c></tag>
+ <item>
+ <p>As long as the length of the message queue is lower than this
+ value, all log events are handled asynchronously. This means that
+ the client process sending the log event, by calling a log function
+ in the <seealso marker="logger_chapter#logger_api">Logger API</seealso>,
+ does not wait for a response from the handler but continues
+ executing immediately after the event is sent. It is not affected
+ by the time it takes the handler to print the event to the log
+ device. If the message queue grows larger than this value,
+ the handler starts handling log events synchronously instead,
+ meaning that the client process sending the event must wait for a
+ response. When the handler reduces the message queue to a
+ level below the <c>sync_mode_qlen</c> threshold, asynchronous
+ operation is resumed. The switch from asynchronous to synchronous
+ mode can slow down the logging tempo of one, or a few, busy senders,
+ but cannot protect the handler sufficiently in a situation of many
+ busy concurrent senders.</p>
+ <p>Defaults to <c>10</c> messages.</p>
+ </item>
+ <tag><c>drop_mode_qlen</c></tag>
+ <item>
+ <p>When the message queue grows larger than this threshold, the
+ handler switches to a mode in which it drops all new events that
+ senders want to log. Dropping an event in this mode means that the
+ call to the log function never results in a message being sent to
+ the handler, but the function returns without taking any action.
+ The handler keeps logging the events that are already in its message
+ queue, and when the length of the message queue is reduced to a level
+ below the threshold, synchronous or asynchronous mode is resumed.
+ Notice that when the handler activates or deactivates drop mode,
+ information about it is printed in the log.</p>
+ <p>Defaults to <c>200</c> messages.</p>
+ </item>
+ <tag><c>flush_qlen</c></tag>
+ <item>
+ <p>If the length of the message queue grows larger than this threshold,
+ a flush (delete) operation takes place. To flush events, the handler
+ discards the messages in the message queue by receiving them in a
+ loop without logging. Client processes waiting for a response from a
+ synchronous log request receive a reply from the handler indicating
+ that the request is dropped. The handler process increases its
+ priority during the flush loop to make sure that no new events
+ are received during the operation. Notice that after the flush operation
+ is performed, the handler prints information in the log about how many
+ events have been deleted.</p>
+ <p>Defaults to <c>1000</c> messages.</p>
+ </item>
+ </taglist>
+
+ <p>For the overload protection algorithm to work properly, it is
+ required that:</p>
+
+ <p><c>sync_mode_qlen =&lt; drop_mode_qlen =&lt; flush_qlen</c></p>
+
+ <p>and that:</p>
+
+ <p><c>drop_mode_qlen &gt; 1</c></p>
+
+ <p>To disable certain modes, do the following:</p>
+ <list>
+ <item>If <c>sync_mode_qlen</c> is set to <c>0</c>, all log events are handled
+ synchronously. That is, asynchronous logging is disabled.</item>
+ <item>If <c>sync_mode_qlen</c> is set to the same value as
+ <c>drop_mode_qlen</c>, synchronous mode is disabled. That is, the handler
+ always runs in asynchronous mode, unless dropping or flushing is invoked.</item>
+ <item>If <c>drop_mode_qlen</c> is set to the same value as <c>flush_qlen</c>,
+ drop mode is disabled and can never occur.</item>
+ </list>
+
+ <p>During high load scenarios, the length of the handler message queue
+ rarely grows in a linear and predictable way. Instead, whenever the
+ handler process is scheduled in, it can have an almost arbitrary number
+ of messages waiting in the message queue. It is for this reason that the overload
+ protection mechanism is focused on acting quickly, and quite drastically,
+ such as immediately dropping or flushing messages, when a large queue length
+ is detected.</p>
+
+ <p>The values of the previously listed thresholds can be specified by the user.
+ This way, a handler can be configured to, for example, not drop or flush
+ messages unless the message queue length of the handler process grows extremely
+ large. Notice that large amounts of memory can be required for the node under such
+ circumstances. Another example of user configuration is when, for performance
+ reasons, the client processes must never be blocked by synchronous log requests.
+ It is possible, perhaps, that dropping or flushing events is still acceptable, since
+ it does not affect the performance of the client processes sending the log events.</p>
+
+ <p>A configuration example:</p>
+ <code type="none">
+logger:add_handler(my_standard_h, logger_std_h,
+ #{config => #{type => {file,"./system_info.log"},
+ sync_mode_qlen => 100,
+ drop_mode_qlen => 1000,
+ flush_qlen => 2000}}).
+ </code>
+ </section>
+
+ <section>
+ <title>Controlling Bursts of Log Requests</title>
+ <p>Large bursts of log events - many events received by the handler
+ under a short period of time - can potentially cause problems, such as:</p>
+ <list>
+ <item>Log files grow very large, very quickly.</item>
+ <item>Circular logs wrap too quickly so that important data is overwritten.</item>
+ <item>Write buffers grow large, which slows down file sync operations.</item>
+ </list>
+
+ <p>For this reason, both built-in handlers offer the possibility to specify the
+ maximum number of events to be handled within a certain time frame.
+ With this burst control feature enabled, the handler can avoid choking the log with
+ massive amounts of printouts. The configuration parameters are:</p>
+ <taglist>
+ <tag><c>burst_limit_enable</c></tag>
+ <item>
+ <p>Value <c>true</c> enables burst control and <c>false</c> disables it.</p>
+ <p>Defaults to <c>true</c>.</p>
+ </item>
+ <tag><c>burst_limit_max_count</c></tag>
+ <item>
+ <p>This is the maximum number of events to handle within a
+ <c>burst_limit_window_time</c> time frame. After the limit is
+ reached, successive events are dropped until the end of the time frame.</p>
+ <p>Defaults to <c>500</c> events.</p>
+ </item>
+ <tag><c>burst_limit_window_time</c></tag>
+ <item>
+ <p>See the previous description of <c>burst_limit_max_count</c>.</p>
+ <p>Defaults to <c>1000</c> milliseconds.</p>
+ </item>
+ </taglist>
+
+ <p>A configuration example:</p>
+ <code type="none">
+logger:add_handler(my_disk_log_h, logger_disk_log_h,
+ #{config => #{file => "./my_disk_log",
+ burst_limit_enable => true,
+ burst_limit_max_count => 20,
+ burst_limit_window_time => 500}}).
+ </code>
+ </section>
+
+ <section>
+ <title>Terminating an Overloaded Handler</title>
+ <p>It is possible that a handler, even if it can successfully manage peaks
+ of high load without crashing, can build up a large message queue, or use a
+ large amount of memory. The overload protection mechanism includes an
+ automatic termination and restart feature for the purpose of guaranteeing
+ that a handler does not grow out of bounds. The feature is configured
+ with the following parameters:</p>
+ <taglist>
+ <tag><c>overload_kill_enable</c></tag>
+ <item>
+ <p>Value <c>true</c> enables the feature and <c>false</c> disables it.</p>
+ <p>Defaults to <c>false</c>.</p>
+ </item>
+ <tag><c>overload_kill_qlen</c></tag>
+ <item>
+ <p>This is the maximum allowed queue length. If the message queue grows
+ larger than this, the handler process is terminated.</p>
+ <p>Defaults to <c>20000</c> messages.</p>
+ </item>
+ <tag><c>overload_kill_mem_size</c></tag>
+ <item>
+ <p>This is the maximum memory size that the handler process is allowed to use.
+ If the handler grows larger than this, the process is terminated.</p>
+ <p>Defaults to <c>3000000</c> bytes.</p>
+ </item>
+ <tag><c>overload_kill_restart_after</c></tag>
+ <item>
+ <p>If the handler is terminated, it restarts automatically after a
+ delay specified in milliseconds. The value <c>infinity</c> prevents
+ restarts.</p>
+ <p>Defaults to <c>5000</c> milliseconds.</p>
+ </item>
+ </taglist>
+ <p>If the handler process is terminated because of overload, it prints
+ information about it in the log. It also prints information about when a
+ restart has taken place, and the handler is back in action.</p>
+ <note>
+ <p>The sizes of the log events affect the memory needs of the handler.
+ For information about how to limit the size of log events, see the
+ <seealso marker="logger_formatter"><c>logger_formatter(3)</c></seealso>
+ manual page.</p>
+ </note>
+ </section>
+ </section>
+
+ <section>
+ <title>See Also</title>
+ <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
new file mode 100644
index 0000000000..dfe2ab3275
--- /dev/null
+++ b/lib/kernel/doc/src/logger_disk_log_h.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2017</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>logger_disk_log_h</title>
+ <prepared></prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <approved></approved>
+ <checked></checked>
+ <date></date>
+ <rev>A</rev>
+ <file>logger_disk_log_h.xml</file>
+ </header>
+ <module>logger_disk_log_h</module>
+ <modulesummary>A disk_log based handler for Logger</modulesummary>
+
+ <description>
+ <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.
+ See an example of this below.</p>
+ <p>The handler has an overload protection mechanism that keeps the handler
+ process and the Kernel application alive during high loads of log
+ events. How overload protection works, and how to configure it, is
+ described in the
+ <seealso marker="logger_chapter#overload_protection"><c>User's Guide</c>
+ </seealso>.</p>
+ <p>To add a new instance of the disk_log handler, use
+ <seealso marker="logger#add_handler-3"><c>logger:add_handler/3</c>
+ </seealso>. The handler configuration argument is a map which can contain
+ general configuration parameters, as documented in the
+ <seealso marker="logger_chapter#handler_configuration"><c>User's Guide</c>
+ </seealso>, and handler specific parameters. The specific data
+ is stored in a sub map with the key <c>config</c>, and can contain the
+ following parameters:</p>
+ <taglist>
+ <tag><c>file</c></tag>
+ <item>
+ <p>This is the full name of the disk log file. The option
+ corresponds to the <c>name</c> property in the
+ <seealso marker="disk_log#open-1"><c>dlog_option()</c></seealso>
+ datatype.</p>
+ </item>
+ <tag><c>type</c></tag>
+ <item>
+ <p>This is the disk log type, <c>wrap</c> or <c>halt</c>. The option
+ corresponds to the <c>type</c> property in the
+ <seealso marker="disk_log#open-1"><c>dlog_option()</c></seealso>
+ datatype.</p>
+ <p>Defaults to <c>wrap</c>.</p>
+ </item>
+ <tag><c>max_no_files</c></tag>
+ <item>
+ <p>This is the maximum number of files that disk_log uses
+ for its circular logging. The option
+ corresponds to the <c>MaxNoFiles</c> element in the <c>size</c> property in the
+ <seealso marker="disk_log#open-1"><c>dlog_option()</c></seealso>
+ datatype.</p>
+ <p>Defaults to <c>10</c>.</p>
+ <p>The setting has no effect on a halt log.</p>
+ </item>
+ <tag><c>max_no_bytes</c></tag>
+ <item>
+ <p>This is the maximum number of bytes that is written to
+ a log file before disk_log proceeds with the next file in order, or
+ generates an error in case of a full halt log. The option
+ corresponds to the <c>MaxNoBytes</c> element in the <c>size</c> property in the
+ <seealso marker="disk_log#open-1"><c>dlog_option()</c></seealso>
+ datatype.</p>
+ <p>Defaults to <c>1048576</c> bytes for a wrap log, and
+ <c>infinity</c> for a halt log.</p>
+ </item>
+ <tag><c>filesync_repeat_interval</c></tag>
+ <item>
+ <p>This value, in milliseconds, specifies how often the handler does
+ a disk_log sync operation to write buffered data to disk. The handler attempts
+ the operation repeatedly, but only performs a new sync if something has
+ actually been logged.</p>
+ <p>Defaults to <c>5000</c> milliseconds.</p>
+ <p>If <c>no_repeat</c> is set as value, the repeated sync operation
+ is disabled. The user can also call the
+ <seealso marker="logger_disk_log_h#filesync-1"><c>filesync/1</c>
+ </seealso> function to perform a disk_log sync.</p>
+ </item>
+ </taglist>
+ <p>Other configuration parameters exist, to be used for customizing
+ the overload protection behaviour. The same parameters are used both in the
+ standard handler and the disk_log handler, and are documented in the
+ <seealso marker="logger_chapter#overload_protection"><c>User's Guide</c>
+ </seealso>.</p>
+ <p>Notice that when changing the configuration of the handler in runtime, the
+ disk_log options (<c>file</c>, <c>type</c>, <c>max_no_files</c>,
+ <c>max_no_bytes</c>) must not be modified.</p>
+ <p>Example of adding a disk_log handler:</p>
+ <code type="none">
+logger:add_handler(my_disk_log_h, logger_disk_log_h,
+ #{config => #{file => "./my_disk_log",
+ type => wrap,
+ max_no_files => 4,
+ max_no_bytes => 10000},
+ filesync_repeat_interval => 1000}}).
+ </code>
+ <p>To use the disk_log handler instead of the default standard
+ handler when starting an Erlang node, change the Kernel default logger to
+ use <c>logger_disk_log_h</c>. Example:</p>
+ <code type="none">
+erl -kernel logger '[{handler,default,logger_disk_log_h,
+ #{config => #{file => "./system_disk_log"}}}]'
+ </code>
+ </description>
+
+ <funcs>
+
+ <func>
+ <name name="filesync" arity="1" clause_i="1"/>
+ <fsummary>Writes buffered data to disk.</fsummary>
+ <desc>
+ <p>Write buffered data to disk.</p>
+ </desc>
+ </func>
+
+ </funcs>
+
+ <section>
+ <title>See Also</title>
+ <p><seealso marker="logger"><c>logger(3)</c></seealso>,
+ <seealso marker="logger_std_h"><c>logger_std_h(3)</c></seealso>,
+ <seealso marker="disk_log"><c>disk_log(3)</c></seealso></p>
+ </section>
+</erlref>
+
+
diff --git a/lib/kernel/doc/src/logger_filters.xml b/lib/kernel/doc/src/logger_filters.xml
new file mode 100644
index 0000000000..90f1fcc270
--- /dev/null
+++ b/lib/kernel/doc/src/logger_filters.xml
@@ -0,0 +1,254 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>logger_filters</title>
+ <prepared></prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <approved></approved>
+ <checked></checked>
+ <date></date>
+ <rev>A</rev>
+ <file>logger_filters.xml</file>
+ </header>
+ <module>logger_filters</module>
+ <modulesummary>Filters to use with Logger.</modulesummary>
+
+ <description>
+ <p>All functions exported from this module can be used as primary
+ or handler
+ filters. See <seealso marker="logger#add_primary_filter-2">
+ <c>logger:add_primary_filter/2</c></seealso>
+ and <seealso marker="logger#add_handler_filter-3">
+ <c>logger:add_handler_filter/3</c></seealso> for more information
+ about how filters are added.</p>
+ <p>Filters are removed with <seealso marker="logger#remove_primary_filter-1">
+ <c>logger:remove_primary_filter/1</c></seealso>
+ and <seealso marker="logger#remove_handler_filter-2">
+ <c>logger:remove_handler_filter/2</c></seealso>.</p>
+ </description>
+
+ <funcs>
+ <func>
+ <name name="domain" arity="2"/>
+ <fsummary>Filter log events based on the domain field in
+ metadata.</fsummary>
+ <desc>
+ <p>This filter provides a way of filtering log events based on a
+ <c>domain</c> field in <c>Metadata</c>. This field is
+ optional, and the purpose of using it is to group log events
+ from, for example, a specific functional area. This allows
+ filtering or other specialized treatment in a Logger
+ handler.</p>
+
+ <p>A domain field must be a list of atoms, creating smaller
+ and more specialized domains as the list grows longer. The
+ greatest domain is <c>[]</c>, which comprises all possible
+ domains.</p>
+
+ <p>For example, consider the following domains:</p>
+ <pre>
+D1 = [otp]
+D2 = [otp, sasl]</pre>
+
+ <p><c>D1</c> is the greatest of the two, and is said to be a
+ super-domain of <c>D2</c>. <c>D2</c> is a
+ sub-domain <c>D1</c>. Both <c>D1</c> and <c>D2</c> are
+ sub-domains of <c>[]</c>.</p>
+
+ <p>The above domains are used for logs originating from
+ Erlang/OTP. D1 specifies that the log event comes from
+ Erlang/OTP in general, and D2 indicates that the log event
+ is a so
+ called <seealso marker="logger_chapter#sasl_reports">SASL
+ report</seealso>.</p>
+
+ <p>The <c><anno>Extra</anno></c> parameter to
+ the <c>domain/2</c> function is specified when adding the
+ filter via <seealso marker="logger#add_primary_filter-2">
+ <c>logger:add_primary_filter/2</c></seealso>
+ or <seealso marker="logger#add_handler_filter-3">
+ <c>logger:add_handler_filter/3</c></seealso>.</p>
+
+ <p>The filter compares the value of the <c>domain</c> field in
+ the log event's metadata (<c>Domain</c>) against
+ <c><anno>MatchDomain</anno></c>. The filter matches if the
+ value of <c>Compare</c> is:</p>
+
+ <taglist>
+ <tag><c>sub</c></tag>
+ <item>
+ <p>and <c>Domain</c> is equal to or a sub-domain
+ of <c>MatchDomain</c>, that is, if <c>MatchDomain</c> is
+ a prefix of <c>Domain</c>.</p>
+ </item>
+ <tag><c>super</c></tag>
+ <item>
+ <p>and <c>Domain</c> is equal to or a super-domain
+ of <c>MatchDomain</c>, that is, if <c>Domain</c> is a
+ prefix of <c>MatchDomain</c>.</p>
+ </item>
+ <tag><c>equal</c></tag>
+ <item>
+ <p>and <c>Domain</c> is equal to <c>MatchDomain</c>.</p>
+ </item>
+ <tag><c>not_equal</c></tag>
+ <item>
+ <p>and <c>Domain</c> differs from <c>MatchDomain</c>, or
+ if there is no domain field in metadata.</p>
+ </item>
+ <tag><c>undefined</c></tag>
+ <item>
+ <p>and there is no domain field in metadata. In this
+ case <c><anno>MatchDomain</anno></c> must be set
+ to <c>[]</c>.</p>
+ </item>
+ </taglist>
+
+ <p>If the filter matches and <c><anno>Action</anno></c> is
+ <c>log</c>, the log event is allowed. If the filter matches
+ and <c><anno>Action</anno></c> is <c>stop</c>, the log event
+ is stopped.</p>
+
+ <p>If the filter does not match, it returns <c>ignore</c>,
+ meaning that other filters, or the value of the
+ configuration parameter <c>filter_default</c>, decide if the
+ event is allowed or not.</p>
+
+ <p>Log events that do not contain any domain field, match only
+ when <c><anno>Compare</anno></c> is equal
+ to <c>undefined</c> or <c>not_equal</c>.</p>
+
+ <p>Example: stop all events with domain <c>[otp,
+ sasl | _]</c></p>
+
+ <code>
+logger:set_handler_config(h1, filter_default, log). % this is the default
+Filter = {fun logger_filters:domain/2, {stop, sub, [otp, sasl]}}.
+logger:add_handler_filter(h1, no_sasl, Filter).
+ok</code>
+ </desc>
+ </func>
+
+ <func>
+ <name name="level" arity="2"/>
+ <fsummary>Filter log events based on the log level.</fsummary>
+ <desc>
+ <p>This filter provides a way of filtering log events based
+ on the log level. It matches log events by comparing the
+ log level with a specified <c>MatchLevel</c></p>
+
+ <p>The <c><anno>Extra</anno></c> parameter is specified when
+ adding the filter
+ via <seealso marker="logger#add_primary_filter-2">
+ <c>logger:add_primary_filter/2</c></seealso>
+ or <seealso marker="logger#add_handler_filter-3">
+ <c>logger:add_handler_filter/3</c></seealso>.</p>
+
+ <p>The filter compares the value of the event's log level
+ (<c>Level</c>) to <c><anno>MatchLevel</anno></c> by
+ calling <seealso marker="logger#compare_levels-2">
+ <c>logger:compare_levels(Level, MatchLevel)</c></seealso>.
+ The filter matches if the value
+ of <c><anno>Operator</anno></c> is:</p>
+
+ <taglist>
+ <tag><c>neq</c></tag>
+ <item><p>and the compare function returns <c>lt</c>
+ or <c>gt</c>.</p></item>
+ <tag><c>eq</c></tag>
+ <item><p>and the compare function returns <c>eq</c>.</p></item>
+ <tag><c>lt</c></tag>
+ <item><p>and the compare function returns <c>lt</c>.</p></item>
+ <tag><c>gt</c></tag>
+ <item><p>and the compare function returns <c>gt</c>.</p></item>
+ <tag><c>lteq</c></tag>
+ <item><p>and the compare function returns <c>lt</c>
+ or <c>eq</c>.</p></item>
+ <tag><c>gteq</c></tag>
+ <item><p>and the compare function returns <c>gt</c>
+ or <c>eq</c>.</p></item>
+ </taglist>
+
+ <p>If the filter matches and <c><anno>Action</anno></c> is
+ <c>log</c>, the log event is allowed. If the filter
+ matches and <c><anno>Action</anno></c> is <c>stop</c>, the
+ log event is stopped.</p>
+
+ <p>If the filter does not match, it returns <c>ignore</c>,
+ meaning that other filters, or the value of the
+ configuration parameter <c>filter_default</c>, will decide
+ if the event is allowed or not.</p>
+
+ <p>Example: only allow debug level log events</p>
+
+ <code>
+logger:set_handler_config(h1, filter_default, stop).
+Filter = {fun logger_filters:level/2, {log, eq, debug}}.
+logger:add_handler_filter(h1, debug_only, Filter).
+ok</code>
+ </desc>
+ </func>
+
+ <func>
+ <name name="progress" arity="2"/>
+ <fsummary>Filter progress reports from supervisor and application_controller.</fsummary>
+ <desc>
+ <p>This filter matches all progress reports
+ from <c>supervisor</c> and <c>application_controller</c>.</p>
+
+ <p>If <c><anno>Extra</anno></c> is <c>log</c>, the progress
+ reports are allowed. If <c><anno>Extra</anno></c>
+ is <c>stop</c>, the progress reports are stopped.</p>
+
+ <p>The filter returns <c>ignore</c> for all other log events.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="remote_gl" arity="2"/>
+ <fsummary>Filter events with group leader on remote node.</fsummary>
+ <desc>
+ <p>This filter matches all events originating from a process
+ that has its group leader on a remote node.</p>
+
+ <p>If <c><anno>Extra</anno></c> is <c>log</c>, the matching
+ events are allowed. If <c><anno>Extra</anno></c>
+ is <c>stop</c>, the matching events are stopped.</p>
+
+ <p>The filter returns <c>ignore</c> for all other log events.</p>
+ </desc>
+ </func>
+
+ </funcs>
+
+ <section>
+ <title>See Also</title>
+ <p>
+ <seealso marker="logger"><c>logger(3)</c></seealso>
+ </p>
+ </section>
+</erlref>
+
+
diff --git a/lib/kernel/doc/src/logger_formatter.xml b/lib/kernel/doc/src/logger_formatter.xml
new file mode 100644
index 0000000000..9226d19834
--- /dev/null
+++ b/lib/kernel/doc/src/logger_formatter.xml
@@ -0,0 +1,355 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2017</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>logger_formatter</title>
+ <prepared></prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <approved></approved>
+ <checked></checked>
+ <date></date>
+ <rev>A</rev>
+ <file>logger_formatter.xml</file>
+ </header>
+ <module>logger_formatter</module>
+ <modulesummary>Default formatter for Logger.</modulesummary>
+
+ <description>
+ <p>Each Logger 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
+ (<seealso marker="stdlib:unicode#type-chardata"><c>unicode:chardata()</c>
+ </seealso>) which can be written to the output device of the
+ handler. See
+ sections <seealso marker="logger_chapter#handlers">Handlers</seealso>
+ and <seealso marker="logger_chapter#formatters">Formatters</seealso>
+ in the Kernel User's Guide for more information.</p>
+ <p><c>logger_formatter</c> is the default formatter used by
+ Logger.</p>
+ </description>
+
+
+ <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><marker id="chars_limit"/>
+ <c>chars_limit = integer() > 0 | 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>
+ </item>
+ <tag><marker id="depth"/><c>depth = integer() > 0 | 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"><c>io:format/2,3</c></seealso>
+ in STDLIB.</p>
+ <p>Defaults to <c>unlimited</c>.</p>
+ </item>
+ <tag><c>encoding = </c><seealso marker="stdlib:unicode#type-encoding">
+ <c>unicode:encoding()</c></seealso></tag>
+ <item>
+ <p>This parameter must reflect the encoding of the device
+ that the handler prints to.</p>
+ <p>Defaults to <c>utf8</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 <seealso marker="error_logger"><c>error_logger</c></seealso>
+ event handlers. It can be included in the log event by
+ adding the list <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><marker id="max_size"/>
+ <c>max_size = integer() > 0 | 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 = </c><seealso marker="logger#type-report_cb">
+ <c>logger:report_cb()</c></seealso></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 exists
+ 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>
+ </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 white spaces following
+ directly after newlines are removed. Notice that newlines
+ added by the <c>template</c> parameter are not replaced.</p>
+ <p>Defaults to <c>true</c>.</p>
+ </item>
+ <tag><marker id="template"/>
+ <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="metakey"/>
+ <desc>
+ <p></p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="template"/>
+ <desc>
+ <p>The template is a list of atoms, atom lists, tuples and strings. The
+ atoms <c>level</c> or <c>msg</c>, are treated as
+ placeholders for the severity level and the log message,
+ respectively. Other atoms or atom lists are interpreted as
+ placeholders for metadata, where atoms are expected to match
+ top level keys, and atom lists represent paths to sub keys when
+ the metadata is a nested map. For example the
+ list <c>[key1,key2]</c> is replaced by the value of
+ the <c>key2</c> field in the nested map below. The
+ atom <c>key1</c> on its own is replaced by the complete
+ value of the <c>key1</c> field. The values are converted to
+ strings.</p>
+
+ <code>
+#{key1 => #{key2 => my_value,
+ ...}
+ ...}</code>
+
+ <p>Tuples in the template express if-exist tests for metadata
+ keys. For example, the following tuple says that
+ if <c>key1</c> exists in the metadata map,
+ print <c>"key1=Value"</c>, where <c>Value</c> is the value
+ that <c>key1</c> is associated with in the metadata map. If
+ <c>key1</c> does not exist, print nothing.</p>
+ <code>
+{key1, ["key1=",key1], []}</code>
+
+ <p>Strings in the template are printed literally.</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>
+?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>
+
+ <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
+ <seealso marker="error_logger"><c>error_logger</c></seealso>
+ produces. 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>
+
+ <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-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>
+ <item>
+ <p>Default template: <c>[time," ",level,":\n",msg,"\n"]</c></p>
+
+ <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>
+ </desc>
+ </datatype>
+ </datatypes>
+
+ <funcs>
+ <func>
+ <name name="check_config" arity="1"/>
+ <fsummary>Validates the given formatter configuration.</fsummary>
+ <desc>
+ <p>The 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>
+ <p>The following Logger API functions can trigger this callback:</p>
+ <list>
+ <item><seealso marker="logger#add_handler-3">
+ <c>logger:add_handler/3</c></seealso></item>
+ <item><seealso marker="logger#set_handler_config-2">
+ <c>logger:set_handler_config/2,3</c></seealso></item>
+ <item><seealso marker="logger#update_handler_config-2">
+ <c>logger:updata_handler_config/2</c></seealso></item>
+ <item><seealso marker="logger#update_formatter_config-2">
+ <c>logger:update_formatter_config/2</c></seealso></item>
+ </list>
+ </desc>
+ </func>
+ <func>
+ <name name="format" arity="2"/>
+ <fsummary>Formats the given message.</fsummary>
+ <desc>
+ <p>This the formatter callback function to be called from
+ handlers. The log event is processed as follows:</p>
+ <list>
+ <item>If the message is on report form, it is converted to
+ <c>{Format,Args}</c> by calling the report callback. See
+ section <seealso marker="logger_chapter#log_message">Log
+ Message</seealso> in the Kernel User's Guide for more
+ information about report callbacks and valid forms of log
+ messages.</item>
+ <item>The message size is limited according to the values of
+ configuration parameters <seealso marker="#chars_limit">
+ <c>chars_limit</c></seealso>
+ and <seealso marker="#depth"><c>depth</c></seealso>.</item>
+ <item>The full log entry is composed according to
+ the <seealso marker="#template"><c>template</c></seealso>.</item>
+ <item>If the final string is too long, it is truncated
+ according to the value of configuration
+ parameter <seealso marker="#max_size"><c>max_size</c></seealso>.</item>
+ </list>
+ </desc>
+ </func>
+ </funcs>
+
+ <section>
+ <title>See Also</title>
+ <p>
+ <seealso marker="stdlib:calendar"><c>calendar(3)</c></seealso>,
+ <seealso marker="error_logger"><c>error_logger(3)</c></seealso>,
+ <seealso marker="stdlib:io"><c>io(3)</c></seealso>,
+ <seealso marker="stdlib:io_lib"><c>io_lib(3)</c></seealso>,
+ <seealso marker="logger"><c>logger(3)</c></seealso>,
+ <seealso marker="stdlib:maps"><c>maps(3)</c></seealso>,
+ <seealso marker="sasl:sasl_app"><c>sasl(6)</c></seealso>,
+ <seealso marker="stdlib:unicode"><c>unicode(3)</c></seealso>
+ </p>
+ </section>
+</erlref>
+
+
diff --git a/lib/kernel/doc/src/logger_std_h.xml b/lib/kernel/doc/src/logger_std_h.xml
new file mode 100644
index 0000000000..b526ed037d
--- /dev/null
+++ b/lib/kernel/doc/src/logger_std_h.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2017</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>logger_std_h</title>
+ <prepared></prepared>
+ <responsible></responsible>
+ <docno></docno>
+ <approved></approved>
+ <checked></checked>
+ <date></date>
+ <rev>A</rev>
+ <file>logger_std_h.xml</file>
+ </header>
+ <module>logger_std_h</module>
+ <modulesummary>Standard handler for Logger.</modulesummary>
+
+ <description>
+ <p>This is the standard handler for Logger.
+ Multiple instances of this handler can be added to
+ Logger, and each instance prints logs to <c>standard_io</c>,
+ <c>standard_error</c>, or to file.</p>
+ <p>The handler has an overload protection mechanism that keeps the handler
+ process and the Kernel application alive during high loads of log
+ events. How overload protection works, and how to configure it, is
+ described in the
+ <seealso marker="logger_chapter#overload_protection"><c>User's Guide</c>
+ </seealso>.</p>
+ <p>To add a new instance of the standard handler, use
+ <seealso marker="logger#add_handler-3"><c>logger:add_handler/3</c>
+ </seealso>. The handler configuration argument is a map which can contain
+ general configuration parameters, as documented in the
+ <seealso marker="logger_chapter#handler_configuration"><c>User's Guide</c>
+ </seealso>, and handler specific parameters. The specific data
+ is stored in a sub map with the key <c>config</c>, and can contain the
+ following parameters:</p>
+ <taglist>
+ <tag><marker id="type"/><c>type</c></tag>
+ <item>
+ <p>This has the value <c>standard_io</c>, <c>standard_error</c>,
+ <c>{file,LogFileName}</c>, or <c>{file,LogFileName,LogFileOpts}</c>.</p>
+ <p> Defaults to <c>standard_io</c>.</p>
+ <p>It is recommended not to specify <c>LogFileOpts</c> unless absolutely
+ necessary. The default options used by the handler to open a file for logging are
+ <c>raw</c>, <c>append</c>, and <c>delayed_write</c>. Notice that the standard
+ handler does not have support for circular logging. Use the disk_log handler,
+ <seealso marker="logger_disk_log_h"><c>logger_disk_log_h</c></seealso>,
+ for this.</p>
+ </item>
+ <tag><c>filesync_repeat_interval</c></tag>
+ <item>
+ <p>This value, in milliseconds, specifies how often the handler does
+ a file sync operation to write buffered data to disk. The handler attempts
+ the operation repeatedly, but only performs a new sync if something has
+ actually been logged.</p>
+ <p>Defaults to <c>5000</c> milliseconds.</p>
+ <p>If <c>no_repeat</c> is set as value, the repeated file sync operation
+ is disabled, and it is the operating system settings that determine
+ how quickly or slowly data is written to disk. The user can also call
+ the <seealso marker="logger_std_h#filesync-1"><c>filesync/1</c></seealso>
+ function to perform a file sync.</p>
+ </item>
+ </taglist>
+ <p>Other configuration parameters exist, to be used for customizing
+ the overload protection behaviour. The same parameters are used both in the
+ standard handler and the disk_log handler, and are documented in the
+ <seealso marker="logger_chapter#overload_protection"><c>User's Guide</c>
+ </seealso>.</p>
+ <p>Notice that if changing the configuration of the handler in runtime,
+ the <c>type</c> parameter must not be modified.</p>
+ <p>Example of adding a standard handler:</p>
+ <code type="none">
+logger:add_handler(my_standard_h, logger_std_h,
+ #{config => #{type => {file,"./system_info.log"},
+ filesync_repeat_interval => 1000}}).
+ </code>
+ <p>To set the default handler, that starts initially with
+ the Kernel application, to log to file instead of <c>standard_io</c>,
+ change the Kernel default logger configuration. Example:</p>
+ <code type="none">
+erl -kernel logger '[{handler,default,logger_std_h,
+ #{config => #{type => {file,"./log.log"}}}}]'
+ </code>
+ <p>An example of how to replace the standard handler with a disk_log handler
+ at startup is found in the
+ <seealso marker="logger_disk_log_h"><c>logger_disk_log_h</c></seealso>
+ manual.</p>
+ </description>
+
+ <funcs>
+
+ <func>
+ <name name="filesync" arity="1" clause_i="1"/>
+ <fsummary>Writes buffered data to disk.</fsummary>
+ <desc>
+ <p>Write buffered data to disk.</p>
+ </desc>
+ </func>
+
+ </funcs>
+
+ <section>
+ <title>See Also</title>
+ <p><seealso marker="logger"><c>logger(3)</c></seealso>,
+ <seealso marker="logger_disk_log_h">
+ <c>logger_disk_log_h(3)</c></seealso></p>
+ </section>
+</erlref>
+
+
diff --git a/lib/kernel/doc/src/net_kernel.xml b/lib/kernel/doc/src/net_kernel.xml
index 0b94fc0fa6..d3bd7365e2 100644
--- a/lib/kernel/doc/src/net_kernel.xml
+++ b/lib/kernel/doc/src/net_kernel.xml
@@ -56,7 +56,7 @@ $ <input>erl -sname foobar</input></pre>
<p>Normally, connections are established automatically when
another node is referenced. This functionality can be disabled
by setting Kernel configuration parameter
- <c>dist_auto_connect</c> to <c>false</c>, see
+ <c>dist_auto_connect</c> to <c>never</c>, see
<seealso marker="kernel_app"><c>kernel(6)</c></seealso>. In this case,
connections must be established explicitly by calling
<seealso marker="#connect_node/1"><c>connect_node/1</c></seealso>.</p>
@@ -102,8 +102,10 @@ $ <input>erl -sname foobar</input></pre>
<fsummary>Establish a connection to a node.</fsummary>
<desc>
<p>Establishes a connection to <c><anno>Node</anno></c>. Returns
- <c>true</c> if successful, <c>false</c> if not, and <c>ignored</c>
- if the local node is not alive.</p>
+ <c>true</c> if a connection was established or was already
+ established or if <c><anno>Node</anno></c> is the local node
+ itself. Returns <c>false</c> if the connection attempt failed, and
+ <c>ignored</c> if the local node is not alive.</p>
</desc>
</func>
@@ -230,7 +232,12 @@ $ <input>erl -sname foobar</input></pre>
<item>
<p>The tuple <c>{nodedown_reason, Reason}</c> is included in
<c>InfoList</c> in <c>nodedown</c> messages.</p>
- <p><c>Reason</c> can be any of the following:</p>
+ <p>
+ <c>Reason</c> can, depending on which
+ distribution module or process that is used be any term,
+ but for the standard TCP distribution module it is
+ any of the following:
+ </p>
<taglist>
<tag><c>connection_setup_failed</c></tag>
<item><p>The connection setup failed (after <c>nodeup</c>
diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml
index 1b7f11d4fa..5884f93878 100644
--- a/lib/kernel/doc/src/notes.xml
+++ b/lib/kernel/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2017</year>
+ <year>2004</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,6 +31,289 @@
</header>
<p>This document describes the changes made to the Kernel application.</p>
+<section><title>Kernel 6.0</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Clarify the documentation of <c>rpc:multicall/5</c>.
+ </p>
+ <p>
+ Own Id: OTP-10551</p>
+ </item>
+ <item>
+ <p>
+ The DNS resolver when getting econnrefused from a server
+ retained an invalid socket so look up towards the next
+ server(s) also failed.</p>
+ <p>
+ Own Id: OTP-13133 Aux Id: PR-1557 </p>
+ </item>
+ <item>
+ <p>
+ No resolver backend returns V4Mapped IPv6 addresses any
+ more. This was inconsistent before, some did, some did
+ not. To facilitate working with such addresses a new
+ function <c>inet:ipv4_mapped_ipv6_address/1</c> has been
+ added.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-13761 Aux Id: ERL-503 </p>
+ </item>
+ <item>
+ <p>
+ The type specifications for <c>file:posix/0</c> and
+ <c>inet:posix/0</c> have been updated according to which
+ errors file and socket operations should be able to
+ return.</p>
+ <p>
+ Own Id: OTP-14019 Aux Id: ERL-550 </p>
+ </item>
+ <item>
+ <p>
+ Fix name resolving in IPv6 only environments when doing
+ the initial distributed connection.</p>
+ <p>
+ Own Id: OTP-14501</p>
+ </item>
+ <item>
+ <p> File operations used to accept <seealso
+ marker="kernel:file#type-name_all">filenames</seealso>
+ containing null characters (integer value zero). This
+ caused the name to be truncated and in some cases
+ arguments to primitive operations to be mixed up.
+ Filenames containing null characters inside the filename
+ are now <em>rejected</em> and will cause primitive file
+ operations to fail. </p> <p> Also environment variable
+ operations used to accept <seealso
+ marker="kernel:os#type-env_var_name">names</seealso> and
+ <seealso
+ marker="kernel:os#type-env_var_value">values</seealso> of
+ environment variables containing null characters (integer
+ value zero). This caused operations to silently produce
+ erroneous results. Environment variable names and values
+ containing null characters inside the name or value are
+ now <em>rejected</em> and will cause environment variable
+ operations to fail. </p> <p>Primitive environment
+ variable operations also used to accept the <c>$=</c>
+ character in environment variable names causing various
+ problems. <c>$=</c> characters in environment variable
+ names are now also <em>rejected</em>. </p> <p>Also
+ <seealso
+ marker="kernel:os#cmd/1"><c>os:cmd/1</c></seealso> now
+ reject null characters inside its <seealso
+ marker="kernel:os#type-os_command">command</seealso>.
+ </p> <p><seealso
+ marker="erts:erlang#open_port/2"><c>erlang:open_port/2</c></seealso>
+ will also reject null characters inside the port name
+ from now on.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-14543 Aux Id: ERL-370 </p>
+ </item>
+ <item>
+ <p><c>os:putenv</c> and <c>os:getenv</c> no longer access
+ the process environment directly and instead work on a
+ thread-safe emulation. The only observable difference is
+ that it's <em>not</em> kept in sync with libc
+ <c>getenv(3)</c> / <c>putenv(3)</c>, so those who relied
+ on that behavior in drivers or NIFs will need to add
+ manual synchronization.</p> <p>On Windows this means that
+ you can no longer resolve DLL dependencies by modifying
+ the <c>PATH</c> just before loading the driver/NIF. To
+ make this less of a problem, the emulator now adds the
+ target DLL's folder to the DLL search path.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-14666</p>
+ </item>
+ <item>
+ <p>
+ Fixed connection tick toward primitive hidden nodes
+ (erl_interface) that could cause faulty tick timeout in
+ rare cases when payload data is sent to hidden node but
+ not received.</p>
+ <p>
+ Own Id: OTP-14681</p>
+ </item>
+ <item>
+ <p>
+ Make group react immediately on an EXIT-signal from shell
+ in e.g ssh.</p>
+ <p>
+ Own Id: OTP-14991 Aux Id: PR1705 </p>
+ </item>
+ <item>
+ <p>
+ Calls to <c>gen_tcp:send/2</c> on closed sockets now
+ returns <c>{error, closed}</c> instead of
+ <c>{error,enotconn}</c>.</p>
+ <p>
+ Own Id: OTP-15001</p>
+ </item>
+ <item>
+ <p>
+ The <c>included_applications</c> key are no longer
+ duplicated as application environment variable. Earlier,
+ the included applications could be read both with
+ <c>application:get[_all]_env(...)</c> and
+ <c>application:get[_all]_key(...)</c> functions. Now, it
+ can only be read with
+ <c>application:get[_all]_key(...)</c>.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-15071</p>
+ </item>
+ <item>
+ <p>Owner and group changes through
+ <c>file:write_file_info</c>, <c>file:change_owner</c>,
+ and <c>file:change_group</c> will no longer report
+ success on permission errors.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-15118</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>A new logging API is added to Erlang/OTP, see the
+ <seealso
+ marker="kernel:logger"><c>logger(3)</c></seealso> manual
+ page, and section <seealso
+ marker="kernel:logger_chapter">Logging</seealso> in the
+ Kernel User's Guide.</p>
+ <p>Calls to <c>error_logger</c> are automatically
+ redirected to the new API, and legacy error logger event
+ handlers can still be used. It is, however, recommended
+ to use the Logger API directly when writing new code.</p>
+ <p>Notice the following potential incompatibilities:</p>
+ <list> <item><p>Kernel configuration parameters
+ <c>error_logger</c> still works, but is overruled if the
+ default handler's output destination is configured with
+ Kernel configuration parameter <c>logger</c>.</p> <p>In
+ general, parameters for configuring error logger are
+ overwritten by new parameters for configuring
+ Logger.</p></item> <item><p>The concept of SASL error
+ logging is deprecated, meaning that by default the SASL
+ application does not affect which log events are
+ logged.</p> <p>By default, supervisor reports and crash
+ reports are logged by the default Logger handler started
+ by Kernel, and end up at the same destination (terminal
+ or file) as other standard log event from Erlang/OTP.</p>
+ <p>Progress reports are not logged by default, but can be
+ enabled by setting the primary log level to info, for
+ example with the Kernel configuration parameter
+ <c>logger_level</c>.</p> <p>To obtain backwards
+ compatibility with the SASL error logging functionality
+ from earlier releases, set Kernel configuration parameter
+ <c>logger_sasl_compatible</c> to <c>true</c>. This
+ prevents the default Logger handler from logging any
+ supervisor-, crash-, or progress reports. Instead, SASL
+ adds a separate Logger handler during application start,
+ which takes care of these log events. The SASL
+ configuration parameters <c>sasl_error_logger</c> and
+ <c>sasl_errlog_type</c> specify the destination (terminal
+ or file) and severity level to log for these
+ events.</p></item></list>
+ <p>
+ Since Logger is new in Erlang/OTP 21.0, we do reserve the
+ right to introduce changes to the Logger API and
+ functionality in patches following this release. These
+ changes might or might not be backwards compatible with
+ the initial version.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-13295</p>
+ </item>
+ <item>
+ <p>
+ The function <c>inet:i/0</c> has been documented.</p>
+ <p>
+ Own Id: OTP-13713 Aux Id: PR-1645 </p>
+ </item>
+ <item>
+ <p>
+ Typespecs for <c>netns</c> and <c>bind_to_device</c>
+ options have been added to <c>gen_tcp</c>, <c>gen_udp</c>
+ and <c>gen_sctp</c> functions.</p>
+ <p>
+ Own Id: OTP-14359 Aux Id: PR-1816 </p>
+ </item>
+ <item>
+ <p>
+ New functionality for implementation of alternative
+ carriers for the Erlang distribution has been introduced.
+ This mainly consists of support for usage of distribution
+ controller processes (previously only ports could be used
+ as distribution controllers). For more information see
+ <seealso marker="erts:alt_dist#distribution_module">ERTS
+ User's Guide ➜ How to implement an Alternative Carrier
+ for the Erlang Distribution ➜ Distribution
+ Module</seealso>.</p>
+ <p>
+ Own Id: OTP-14459</p>
+ </item>
+ <item>
+ <p><c>seq_trace</c> labels may now be any erlang
+ term.</p>
+ <p>
+ Own Id: OTP-14899</p>
+ </item>
+ <item>
+ <p>
+ The SSL distribution protocol <c>-proto inet_tls</c> has
+ stopped setting the SSL option
+ <c>server_name_indication</c>. New verify funs for client
+ and server in <c>inet_tls_dist</c> has been added, not
+ documented yet, that checks node name if present in peer
+ certificate. Usage is still also yet to be documented.</p>
+ <p>
+ Own Id: OTP-14969 Aux Id: OTP-14465, ERL-598 </p>
+ </item>
+ <item>
+ <p>
+ Changed timeout of <c>gen_server</c> calls to <c>auth</c>
+ server from default 5 seconds to <c>infinity</c>.</p>
+ <p>
+ Own Id: OTP-15009 Aux Id: ERL-601 </p>
+ </item>
+ <item>
+ <p>The callback module passed as <c>-epmd_module</c> to
+ erl has been expanded to be able to do name and port
+ resolving.</p> <p>Documentation has also been added in
+ the <seealso
+ marker="kernel:erl_epmd"><c>erl_epmd</c></seealso>
+ reference manual and ERTS User's Guide <seealso
+ marker="erts:alt_disco">How to Implement an Alternative
+ Service Discovery for Erlang Distribution</seealso>.</p>
+ <p>
+ Own Id: OTP-15086 Aux Id: PR-1694 </p>
+ </item>
+ <item>
+ <p>
+ Included config file specified with relative path in
+ sys.config are now first searched for relative to the
+ directory of sys.config itself. If not found, it is also
+ searched for relative to the current working directory.
+ The latter is for backwards compatibility.</p>
+ <p>
+ Own Id: OTP-15137 Aux Id: PR-1838 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Kernel 5.4.3.2</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/kernel/doc/src/os.xml b/lib/kernel/doc/src/os.xml
index 7ce2f54542..c95e615c6b 100644
--- a/lib/kernel/doc/src/os.xml
+++ b/lib/kernel/doc/src/os.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1997</year><year>2017</year>
+ <year>1997</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -36,11 +36,85 @@
only run on a specific platform. On the other hand, with careful
use, these functions can be of help in enabling a program to run on
most platforms.</p>
+
+ <note>
+ <p>
+ File operations used to accept filenames containing
+ null characters (integer value zero). This caused
+ the name to be truncated and in some cases arguments
+ to primitive operations to be mixed up. Filenames
+ containing null characters inside the filename
+ are now <em>rejected</em> and will cause primitive
+ file operations to fail.
+ </p>
+ <p>
+ Also environment variable operations used to accept
+ names and values of environment variables containing
+ null characters (integer value zero). This caused
+ operations to silently produce erroneous results.
+ Environment variable names and values containing
+ null characters inside the name or value are now
+ <em>rejected</em> and will cause environment variable
+ operations to fail.
+ </p>
+ </note>
</description>
<datatypes>
<datatype>
+ <name name="env_var_name"/>
+ <desc>
+ <p>A string containing valid characters on the specific
+ OS for environment variable names using
+ <seealso marker="file#native_name_encoding/0"><c>file:native_name_encoding()</c></seealso>
+ encoding. Note that specifically null characters (integer
+ value zero) and <c>$=</c> characters are not allowed.
+ However, note that not all invalid characters necessarily
+ will cause the primitiv operations to fail, but may instead
+ produce invalid results.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="env_var_value"/>
+ <desc>
+ <p>A string containing valid characters on the specific
+ OS for environment variable values using
+ <seealso marker="file#native_name_encoding/0"><c>file:native_name_encoding()</c></seealso>
+ encoding. Note that specifically null characters (integer
+ value zero) are not allowed. However, note that not all
+ invalid characters necessarily will cause the primitiv
+ operations to fail, but may instead produce invalid results.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="env_var_name_value"/>
+ <desc>
+ <p>
+ Assuming that environment variables has been correctly
+ set, a strings containing valid characters on the specific
+ OS for environment variable names and values using
+ <seealso marker="file#native_name_encoding/0"><c>file:native_name_encoding()</c></seealso>
+ encoding. The first <c>$=</c> characters appearing in
+ the string separates environment variable name (on the
+ left) from environment variable value (on the right).
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
<name name="os_command"/>
+ <desc>
+ <p>All characters needs to be valid characters on the
+ specific OS using
+ <seealso marker="file#native_name_encoding/0"><c>file:native_name_encoding()</c></seealso>
+ encoding. Note that specifically null characters (integer
+ value zero) are not allowed. However, note that not all
+ invalid characters not necessarily will cause
+ <seealso marker="#cmd/1"><c>os:cmd/1</c></seealso>
+ to fail, but may instead produce invalid results.
+ </p>
+ </desc>
</datatype>
<datatype>
<name name="os_command_opts"/>
@@ -65,8 +139,13 @@
<fsummary>Execute a command in a shell of the target OS.</fsummary>
<desc>
<p>Executes <c><anno>Command</anno></c> in a command shell of the
- target OS, captures the standard output of the command,
+ target OS, captures the standard output of the command,
and returns this result as a string.</p>
+ <warning><p>Previous implementation used to allow all characters
+ as long as they were integer values greater than or equal to zero.
+ This sometimes lead to unwanted results since null characters
+ (integer value zero) often are interpreted as string termination. The
+ current implementation rejects these.</p></warning>
<p><em>Examples:</em></p>
<code type="none">
LsOut = os:cmd("ls"), % on unix platform
@@ -185,6 +264,15 @@ DirOut = os:cmd("dir"), % on Win32 platform</code>
<p>On Unix platforms, the environment is set using UTF-8 encoding
if Unicode filename translation is in effect. On Windows, the
environment is set using wide character interfaces.</p>
+ <note>
+ <p>
+ <c><anno>VarName</anno></c> is not allowed to contain
+ an <c>$=</c> character. Previous implementations used
+ to just let the <c>$=</c> character through which
+ silently caused erroneous results. Current implementation
+ will instead throw a <c>badarg</c> exception.
+ </p>
+ </note>
</desc>
</func>
diff --git a/lib/kernel/doc/src/part.xml b/lib/kernel/doc/src/part.xml
new file mode 100644
index 0000000000..fa7e92835f
--- /dev/null
+++ b/lib/kernel/doc/src/part.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE part SYSTEM "part.dtd">
+
+<part xmlns:xi="http://www.w3.org/2001/XInclude">
+ <header>
+ <copyright>
+ <year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>Kernel User's Guide</title>
+ <prepared>OTP Team</prepared>
+ <docno></docno>
+ <date>2018-06-06</date>
+ <file>part.xml</file>
+ </header>
+ <description>
+ <p></p>
+ </description>
+ <xi:include href="introduction_chapter.xml"/>
+ <xi:include href="logger_chapter.xml"/>
+</part>
+
diff --git a/lib/kernel/doc/src/ref_man.xml b/lib/kernel/doc/src/ref_man.xml
index 5cd77e0f6f..d3b947527f 100644
--- a/lib/kernel/doc/src/ref_man.xml
+++ b/lib/kernel/doc/src/ref_man.xml
@@ -4,7 +4,7 @@
<application xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,12 +32,15 @@
</description>
<xi:include href="kernel_app.xml"/>
+ <xi:include href="app.xml"/>
<xi:include href="application.xml"/>
<xi:include href="auth.xml"/>
<xi:include href="code.xml"/>
+ <xi:include href="config.xml"/>
<xi:include href="disk_log.xml"/>
<xi:include href="erl_boot_server.xml"/>
<xi:include href="erl_ddll.xml"/>
+ <xi:include href="erl_epmd.xml"/>
<xi:include href="erl_prim_loader_stub.xml"/>
<xi:include href="erlang_stub.xml"/>
<xi:include href="error_handler.xml"/>
@@ -52,6 +55,11 @@
<xi:include href="inet.xml"/>
<xi:include href="inet_res.xml"/>
<xi:include href="init_stub.xml"/>
+ <xi:include href="logger.xml"/>
+ <xi:include href="logger_filters.xml"/>
+ <xi:include href="logger_formatter.xml"/>
+ <xi:include href="logger_std_h.xml"/>
+ <xi:include href="logger_disk_log_h.xml"/>
<xi:include href="net_adm.xml"/>
<xi:include href="net_kernel.xml"/>
<xi:include href="os.xml"/>
@@ -61,6 +69,4 @@
<xi:include href="user.xml"/>
<xi:include href="wrap_log_reader.xml"/>
<xi:include href="zlib_stub.xml"/>
- <xi:include href="app.xml"/>
- <xi:include href="config.xml"/>
</application>
diff --git a/lib/kernel/doc/src/rpc.xml b/lib/kernel/doc/src/rpc.xml
index adec2d9520..fab616e630 100644
--- a/lib/kernel/doc/src/rpc.xml
+++ b/lib/kernel/doc/src/rpc.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -217,7 +217,7 @@
<list type="bulleted">
<item>A list of the nodes that do not exist</item>
<item>A list of the nodes where the server does not exist</item>
- <item>A list of the nodes where the server terminatd before sending
+ <item>A list of the nodes where the server terminated before sending
any reply.</item>
</list>
</desc>
@@ -268,8 +268,9 @@
on the specified nodes and collects the answers. It returns
<c>{<anno>ResL</anno>, <anno>BadNodes</anno>}</c>, where
<c><anno>BadNodes</anno></c> is a list
- of the nodes that terminated or timed out during computation,
- and <c><anno>ResL</anno></c> is a list of the return values.
+ of the nodes that do not exist,
+ and <c><anno>ResL</anno></c> is a list of the return values,
+ or <c>{badrpc, <anno>Reason</anno>}</c> for failing calls.
<c><anno>Timeout</anno></c> is a time (integer) in milliseconds, or
<c>infinity</c>.</p>
<p>The following example is useful when new object code is to
@@ -347,7 +348,7 @@
<func>
<name name="pmap" arity="3"/>
- <fsummary>Parallell evaluation of mapping a function over a
+ <fsummary>Parallel evaluation of mapping a function over a
list.</fsummary>
<desc>
<p>Evaluates <c>apply(<anno>Module</anno>, <anno>Function</anno>,
diff --git a/lib/kernel/doc/src/seq_trace.xml b/lib/kernel/doc/src/seq_trace.xml
index 197851021f..1a4a74419a 100644
--- a/lib/kernel/doc/src/seq_trace.xml
+++ b/lib/kernel/doc/src/seq_trace.xml
@@ -4,7 +4,7 @@
<erlref>
<header>
<copyright>
- <year>1998</year><year>2017</year>
+ <year>1998</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -80,13 +80,18 @@ seq_trace:set_token(OldToken), % activate the trace token again
<p>Sets the individual <c><anno>Component</anno></c> of the trace token to
<c><anno>Val</anno></c>. Returns the previous value of the component.</p>
<taglist>
- <tag><c>set_token(label, <anno>Integer</anno>)</c></tag>
+ <tag><c>set_token(label, <anno>Label</anno>)</c></tag>
<item>
- <p>The <c>label</c> component is an integer which
+ <p>The <c>label</c> component is a term which
identifies all events belonging to the same sequential
trace. If several sequential traces can be active
simultaneously, <c>label</c> is used to identify
the separate traces. Default is 0.</p>
+ <warning>
+ <p>Labels were restricted to small signed integers (28 bits)
+ prior to OTP 21. The trace token will be silenty dropped if it
+ crosses over to a node that does not support the label.</p>
+ </warning>
</item>
<tag><c>set_token(serial, SerialValue)</c></tag>
<item>
diff --git a/lib/kernel/doc/src/specs.xml b/lib/kernel/doc/src/specs.xml
index 29d52f23bb..b8c25ca53b 100644
--- a/lib/kernel/doc/src/specs.xml
+++ b/lib/kernel/doc/src/specs.xml
@@ -6,6 +6,7 @@
<xi:include href="../specs/specs_disk_log.xml"/>
<xi:include href="../specs/specs_erl_boot_server.xml"/>
<xi:include href="../specs/specs_erl_ddll.xml"/>
+ <xi:include href="../specs/specs_erl_epmd.xml"/>
<xi:include href="../specs/specs_erl_prim_loader_stub.xml"/>
<xi:include href="../specs/specs_erlang_stub.xml"/>
<xi:include href="../specs/specs_error_handler.xml"/>
@@ -20,6 +21,11 @@
<xi:include href="../specs/specs_inet.xml"/>
<xi:include href="../specs/specs_inet_res.xml"/>
<xi:include href="../specs/specs_init_stub.xml"/>
+ <xi:include href="../specs/specs_logger.xml"/>
+ <xi:include href="../specs/specs_logger_filters.xml"/>
+ <xi:include href="../specs/specs_logger_formatter.xml"/>
+ <xi:include href="../specs/specs_logger_std_h.xml"/>
+ <xi:include href="../specs/specs_logger_disk_log_h.xml"/>
<xi:include href="../specs/specs_net_adm.xml"/>
<xi:include href="../specs/specs_net_kernel.xml"/>
<xi:include href="../specs/specs_os.xml"/>