From 0deea4a8f369013ec00e231d0c2c37e4ab3f0ba1 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Tue, 24 Apr 2018 14:26:31 +0200 Subject: Add logger --- lib/kernel/doc/src/Makefile | 21 +- lib/kernel/doc/src/book.xml | 3 + lib/kernel/doc/src/introduction_chapter.xml | 64 +++ lib/kernel/doc/src/logger.xml | 478 +++++++++++++++++++++ lib/kernel/doc/src/logger_arch.png | Bin 0 -> 31459 bytes lib/kernel/doc/src/logger_chapter.xml | 641 ++++++++++++++++++++++++++++ lib/kernel/doc/src/logger_filters.xml | 191 +++++++++ lib/kernel/doc/src/logger_formatter.xml | 149 +++++++ lib/kernel/doc/src/logger_std_h.xml | 81 ++++ lib/kernel/doc/src/part.xml | 40 ++ lib/kernel/doc/src/ref_man.xml | 4 + lib/kernel/doc/src/specs.xml | 4 + 12 files changed, 1671 insertions(+), 5 deletions(-) create mode 100644 lib/kernel/doc/src/introduction_chapter.xml create mode 100644 lib/kernel/doc/src/logger.xml create mode 100644 lib/kernel/doc/src/logger_arch.png create mode 100644 lib/kernel/doc/src/logger_chapter.xml create mode 100644 lib/kernel/doc/src/logger_filters.xml create mode 100644 lib/kernel/doc/src/logger_formatter.xml create mode 100644 lib/kernel/doc/src/logger_std_h.xml create mode 100644 lib/kernel/doc/src/part.xml (limited to 'lib/kernel/doc') diff --git a/lib/kernel/doc/src/Makefile b/lib/kernel/doc/src/Makefile index 2413541082..10bdf46119 100644 --- a/lib/kernel/doc/src/Makefile +++ b/lib/kernel/doc/src/Makefile @@ -56,6 +56,10 @@ XML_REF3_FILES = application.xml \ inet.xml \ inet_res.xml \ init_stub.xml \ + logger.xml \ + logger_std_h.xml \ + logger_filters.xml \ + logger_formatter.xml \ net_adm.xml \ net_kernel.xml \ os.xml \ @@ -70,11 +74,17 @@ 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 +IMAGE_FILES = \ + logger_arch.png + XML_FILES = \ $(BOOK_FILES) $(XML_CHAPTER_FILES) \ $(XML_PART_FILES) $(XML_REF3_FILES) $(XML_REF4_FILES)\ @@ -111,7 +121,7 @@ SPECS_FLAGS = -I../../include # ---------------------------------------------------- # Targets # ---------------------------------------------------- -$(HTMLDIR)/%.gif: %.gif +$(HTMLDIR)/%: % $(INSTALL_DATA) $< $@ docs: man pdf html @@ -120,11 +130,12 @@ $(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: diff --git a/lib/kernel/doc/src/book.xml b/lib/kernel/doc/src/book.xml index 81a87d126d..0b69b547e7 100644 --- a/lib/kernel/doc/src/book.xml +++ b/lib/kernel/doc/src/book.xml @@ -34,6 +34,9 @@ + + + diff --git a/lib/kernel/doc/src/introduction_chapter.xml b/lib/kernel/doc/src/introduction_chapter.xml new file mode 100644 index 0000000000..6e6990ddda --- /dev/null +++ b/lib/kernel/doc/src/introduction_chapter.xml @@ -0,0 +1,64 @@ + + + + +
+ + 2017 + Ericsson AB. 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. + 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. + + + + Introduction + + + + + + + + introduction.xml +
+ +
+ Scope +

The Kernel application has all the code necessary to run + the Erlang runtime system: file servers, code servers, + and so on.

+

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:

+ + Start, stop, supervision, configuration, and distribution of applications + Code loading + Logging + Error logging + Global name service + Supervision of Erlang/OTP + Communication with sockets + Operating system interface + +
+ +
+ Prerequisites +

It is assumed that the reader is familiar with the Erlang programming + language.

+
+
+ + diff --git a/lib/kernel/doc/src/logger.xml b/lib/kernel/doc/src/logger.xml new file mode 100644 index 0000000000..66e6e5c689 --- /dev/null +++ b/lib/kernel/doc/src/logger.xml @@ -0,0 +1,478 @@ + + + + +
+ + 2017 + Ericsson AB. 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. + 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. + + + + logger + + + + + + + A + logger.xml +
+ logger + API module for the logger application. + + + + + + + + + +

The severity level for the message to be logged.

+
+
+ + + +

+
+
+ + + +

+
+
+ + + +

+
+
+ + + +

Metadata associated with the message to be logged.

+
+
+ + + +

+
+
+ + + +

+
+
+ + + +

+
+
+ + + +

+
+
+ + + +

+
+
+
+ +
+ Macros +

The following macros are defined:

+ + + ?LOG_EMERGENCY(StringOrReport[,Metadata]) + ?LOG_EMERGENCY(FunOrFormat,Args[,Metadata]) + ?LOG_ALERT(StringOrReport[,Metadata]) + ?LOG_ALERT(FunOrFormat,Args[,Metadata]) + ?LOG_CRITICAL(StringOrReport[,Metadata]) + ?LOG_CRITICAL(FunOrFormat,Args[,Metadata]) + ?LOG_ERROR(StringOrReport[,Metadata]) + ?LOG_ERROR(FunOrFormat,Args[,Metadata]) + ?LOG_WARNING(StringOrReport[,Metadata]) + ?LOG_WARNING(FunOrFormat,Args[,Metadata]) + ?LOG_NOTICE(StringOrReport[,Metadata]) + ?LOG_NOTICE(FunOrFormat,Args[,Metadata]) + ?LOG_INFO(StringOrReport[,Metadata]) + ?LOG_INFO(FunOrFormat,Args[,Metadata]) + ?LOG_DEBUG(StringOrReport[,Metadata]) + ?LOG_DEBUG(FunOrFormat,Args[,Metadata]) + + +

All macros expand to a call to logger, where Level is + taken from the macro name, and the following metadata is added, + or merged with the given Metadata:

+ + +#{mfa=>{?MODULE,?FUNCTION_NAME,?FUNCTION_ARITY}, + file=>?FILE, + line=>?LINE} + + +

The call is wrapped in a case statement and will be evaluated + only if Level is equal to or below the configured log + level.

+
+ + + + emergency(StringOrReport[,Metadata]) + emergency(Format,Args[,Metadata]) + emergency(Fun,FunArgs[,Metadata]) + Logs the given message as level emergency. + +

Equivalent to + log(emergency,...).

+
+
+ + + alert(StringOrReport[,Metadata]) + alert(Format,Args[,Metadata]) + alert(Fun,FunArgs[,Metadata]) + Logs the given message as level alert. + +

Equivalent to + log(alert,...).

+
+
+ + + critical(StringOrReport[,Metadata]) + critical(Format,Args[,Metadata]) + critical(Fun,FunArgs[,Metadata]) + Logs the given message as level critical. + +

Equivalent to + log(critical,...).

+
+
+ + + error(StringOrReport[,Metadata]) + error(Format,Args[,Metadata]) + error(Fun,FunArgs[,Metadata]) + Logs the given message as level error. + +

Equivalent to + log(error,...).

+
+
+ + + warning(StringOrReport[,Metadata]) + warning(Format,Args[,Metadata]) + warning(Fun,FunArgs[,Metadata]) + Logs the given message as level warning. + +

Equivalent to + log(warning,...).

+
+
+ + + notice(StringOrReport[,Metadata]) + notice(Format,Args[,Metadata]) + notice(Fun,FunArgs[,Metadata]) + Logs the given message as level notice. + +

Equivalent to + log(notice,...).

+
+
+ + + info(StringOrReport[,Metadata]) + info(Format,Args[,Metadata]) + info(Fun,FunArgs[,Metadata]) + Logs the given message as level info. + +

Equivalent to + log(info,...).

+
+
+ + + debug(StringOrReport[,Metadata]) + debug(Format,Args[,Metadata]) + debug(Fun,FunArgs[,Metadata]) + Logs the given message as level debug. + +

Equivalent to + log(debug,...).

+
+
+ + + + + + + + + Logs the given message. + + + + + + + + +

Log the given message.

+
+
+ + + + Lookup the current configuration for logger. + +

Lookup the current configuration for logger.

+
+
+ + + + Lookup the current configuration for the given handler. + +

Lookup the current configuration for the given handler.

+
+
+ + + + Get information about all logger configurations + +

Same as logger:i(term)

+
+
+ + + + + + Get information about all logger configurations + +

The logger:i/1 function can be used to get all + current logger configuration. The way that the information + is returned depends on the Action

+ + string + Return the pretty printed current logger configuration + as iodata. + term + Return the current logger configuration as a term. The + format of this term may change inbetween releases. For a + stable format use + logger:get_handler_config/1 + and + logger:get_logger_config/0. + The same as calling logger:i(). + print + Pretty print all the current logger configuration to + standard out. Example: + logger:i(). +Current logger configuration: + Level: info + FilterDefault: log + Filters: + Handlers: + Id: logger_std_h + Module: logger_std_h + Level: info + Formatter: + Module: logger_formatter + Config: #{template => [{logger_formatter,header},"\n",msg,"\n"], + legacy_header => true} + Filter Default: stop + Filters: + Id: stop_progress + Fun: fun logger_filters:progress/2 + Config: stop + Id: remote_gl + Fun: fun logger_filters:remote_gl/2 + Config: stop + Id: domain + Fun: fun logger_filters:domain/2 + Config: {log,prefix_of,[beam,erlang,otp,sasl]} + Id: no_domain + Fun: fun logger_filters:domain/2 + Config: {log,no_domain,[]} + Handler Config: + logger_std_h: #{type => standard_io} + Level set per module: + Module: my_module + Level: debug]]> + + +
+
+ + + + Add a filter to the logger. + +

Add a filter to the logger.

+
+
+ + + + Add a filter to the specified handler. + +

Add a filter to the specified handler.

+
+
+ + + + Remove a filter from the logger. + +

Remove the filter with the specified identity from the logger.

+
+
+ + + + Remove a filter from the specified handler. + +

Remove the filter with the specified identity from the given handler.

+
+
+ + + + Add a handler with the given configuration. + +

Add a handler with the given configuration.

+
+
+ + + + Remove the handler with the specified identity. + +

Remove the handler with the specified identity.

+
+
+ + + + Set the log level for the specified module. + +

Set the log level for the specified module.

+

To change the logging level globally, use + logger:set_logger_config(level, Level). +

+
+
+ + + + Remove a module specific log setting. + +

Remove a module specific log setting. After this, the + global log level is used for the specified module.

+
+
+ + + + + Add or update configuration data for the logger. + +

Add or update configuration data for the logger.

+
+
+ + + + + Add or update configuration data for the specified + handler. + +

Add or update configuration data for the specified + handler.

+
+
+ + + + Compare the severity of two log levels. + +

Compare the severity of two log levels. Returns gt + if Level1 is more severe than + Level2, lt if Level1 is less severe, + and eq if the levels are equal.

+
+
+ + + + Set metadata to use when logging from current process. + +

Set metadata which logger automatically inserts it + in all log events produced on the current + process. Subsequent calls will overwrite previous data set + by this function.

+

When logging, location data produced by the log macros, + and/or metadata given as argument to the log call (API + function or macro), will be merged with the process + metadata. If the same keys occur, values from the metadata + argument to the log call will overwrite values in the + process metadata, which in turn will overwrite values from + the location data.

+
+
+ + + + Retrieve data set with set_process_metadata/1. + +

Retrieve data set + with + set_process_metadata/1.

+
+
+ + + + Delete data set with set_process_metadata/1. + +

Delete data set + with + set_process_metadata/1.

+
+
+ +
+ +
+ + diff --git a/lib/kernel/doc/src/logger_arch.png b/lib/kernel/doc/src/logger_arch.png new file mode 100644 index 0000000000..727609a6ef Binary files /dev/null and b/lib/kernel/doc/src/logger_arch.png 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..2a325453da --- /dev/null +++ b/lib/kernel/doc/src/logger_chapter.xml @@ -0,0 +1,641 @@ + + + + +
+ + 2017 + Ericsson AB. 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. + 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. + + + + Logging + + + + + logger_chapter.xml +
+ +
+ Overview +

Erlang/OTP provides a standard API for logging. The backend of + this API can be used as is, or it can be customized to suite + specific needs.

+

It consists of two parts - the logger part and the + handler part. The logger will forward log events to one + or more handler(s).

+ + + Conceptual overview + + +

Filters can be added to the logger and to each + handler. The filters decide if an event is to be forwarded or + not, and they can also modify all parts of the log event.

+ +

A formatter can be set for each handler. The formatter + does the final formatting of the log event, including the log + message itself, and possibly a timestamp, header and other + metadata.

+ +

In accordance with the Syslog protocol, RFC-5424, eight + severity levels can be specified:

+ + + + Level + Integer + Description + + + emergency + 0 + system is unusable + + + alert + 1 + action must be taken immediately + + + critical + 2 + critical contidions + + + error + 3 + error conditions + + + warning + 4 + warning conditions + + + notice + 5 + normal but significant conditions + + + info + 6 + informational messages + + + debug + 7 + debug-level messages + + Severity levels +
+ +

A log event is allowed by Logger if the integer value of + its Level is less than or equal to the currently + configured log level. The log level can be configured globally, + or to allow more verbose logging from a specific part of the + system, per module.

+ +
+ Customizable parts + + + Handler + +

A handler is defined as a module exporting the following + function:

+ + log(Log, Config) -> ok + +

A handler is called by the logger backend after filtering on + logger level and on handler level for the handler which is + about to be called. The function call is done on the client + process, and it is up to the handler implementation if other + processes are to be involved or not.

+ +

Multiple instances of the same handler can be + added. Configuration is per instance.

+ +
+ + Filter + +

Filters can be set on the logger or on a handler. Logger + filters are applied first, and if passed, the handler filters + for each handler are applied. The handler plugin is only + called if all handler filters for the handler in question also + pass.

+ +

A filter is specified as:

+ + {fun((Log,Extra) -> Log | stop | ignore), Extra} + +

The configuration parameter filter_default + specifies the behavior if all filters return ignore. + filter_default is by default set to log.

+ +

The Extra parameter may contain any data that the + filter needs.

+
+ + Formatter + +

A formatter is defined as a module exporting the following + function:

+ + format(Log,Extra) -> string() + +

The formatter plugin is called by each handler, and the + returned string can be printed to the handler's destination + (stdout, file, ...).

+
+ +
+
+ +
+ Built-in handlers + + + logger_std_h + +

This is the default handler used by OTP. Multiple instances + can be started, and each instance will write log events to a + given destination, console or file. Filters can be used for + selecting which event to send to which handler instance.

+
+ + logger_disk_log_h + +

This handler behaves much like logger_std_h, except it uses + disk_log as its + destination.

+
+ + error_logger + +

This handler is to be used for backwards compatibility + only. It is not started by default, but will be automatically + started the first time an event handler is added + with + error_logger:add_report_handler/1,2.

+ +

No built-in event handlers exist.

+
+
+
+ +
+ Built-in filters + + + logger_filters:domain/2 + +

This filter provides a way of filtering log events based on a + domain field Metadata. See + + logger_filters:domain/2

+
+ + logger_filters:level/2 + +

This filter provides a way of filtering log events based + on the log level. See + logger_filters:domain/2

+
+ + logger_filters:progress/2 + +

This filter matches all progress reports + from supervisor and application_controller. + See + logger_filters:progress/2

+
+ + logger_filters:remote_gl/2 + +

This filter matches all events originating from a process + that has its group leader on a remote node. + See + logger_filters:remote_gl/2

+
+
+
+ +
+ Default formatter + +

The default formatter is logger_formatter. + See + logger_formatter:format/2.

+
+
+ +
+ Configuration + +
+ Application environment variables +

See Kernel(6) for + information about the application environment variables that can + be used for configuring logger.

+
+ +
+ Logger configuration + + + level + +

Specifies the severity level to log.

+
+ filters + +

Logger filters are added or removed with + + logger:add_logger_filter/2 and + + logger:remove_logger_filter/1, + respectively.

+

See Filter for more + information.

+

By default, no filters exist.

+
+ filter_default = log | stop + +

Specifies what to do with an event if all filters + return ignore.

+

Default is log.

+
+ handlers + +

Handlers are added or removed with + + logger:add_handler/3 and + + logger:remove_handler/1, + respectively.

+

See Handler for more + information.

+
+
+
+ +
+ Handler configuration + + level + +

Specifies the severity level to log.

+
+ filters + +

Handler filters can be specified when adding the handler, + or added or removed later with + + logger:add_handler_filter/3 and + + logger:remove_handler_filter/2, + respectively.

+

See Filter for more + information.

+

By default, no filters exist.

+
+ filter_default = log | stop + +

Specifies what to do with an event if all filters + return ignore.

+

Default is log.

+
+ depth = pos_integer() | unlimited + +

Specifies if the depth of terms in the log events shall + be limited by using control characters ~P + and ~W instead of ~p and ~w, + respectively. See + io:format.

+
+ max_size = pos_integer() | unlimited + +

Specifies if the size of a log event shall be limited by + truncating the formatted string.

+
+ formatter = {Module::module(),Extra::term()} + +

See Formatter for more + information.

+

The default module is + logger_formatter, and Extra is + it's configuration map.

+
+
+ +

Note that level and filters are obeyed by + Logger itself before forwarding the log events to each + handler, while depth, max_size + and formatter are left to the handler + implementation. All Logger's built-in handlers do apply these + configuration parameters before printing.

+
+ +
+ +
+ + Backwards compatibility with error_logger +

Logger provides backwards compatibility with the old + error_logger in the following ways:

+ + + Legacy event handlers + +

To use event handlers written for error_logger, just + add your event handler with

+ +error_logger:add_report_handler/1,2. + +

This will automatically start the error_logger + event manager, and add error_logger as a + handler to logger, with configuration

+ +#{level=>info, + filter_default=>log, + filters=>[]}. + +

Note that this handler will ignore events that do not + originate from the old error_logger 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.

+

Also note that error_logger is not overload + protected.

+
+ Logger API + +

The old error_logger API still exists, but should + only be used by legacy code. It will be removed in a later + release.

+
+ Output format + +

To get log events on the same format as produced + by error_logger_tty_h and error_logger_file_h, + use the default formatter, logger_formatter, with + configuration parameter legacy_header=>true. This is + also the default.

+
+ Default format of log events from OTP + +

By default, all log events originating from within OTP, + except the former so called "SASL reports", look the same as + before.

+
+ SASL reports + +

By SASL reports we mean supervisor reports, crash reports + and progress reports.

+

In earlier releases, these reports were only logged when + the SASL application was running, and they were printed + trough specific event handlers + named sasl_report_tty_h + and sasl_report_file_h.

+

The destination of these log events were configured by + environment variables for the SASL application.

+

Due to the specific event handlers, the output format + slightly differed from other log events.

+

As of OTP-21, the concept of SASL reports is removed, + meaning that the default behavior is as follows:

+ + Supervisor reports, crash reports and progress reports + are no longer connected to the SASL application. + Supervisor reports and crash reports are logged by + default. + Progress reports are not logged by default, but can be + enabled with the kernel environment + variable logger_log_progress. + The output format is the same for all log + events. + +

If the old behavior is preferred, the kernel environment + variable logger_sasl_compatible can be set + to true. The old SASL environment variables can then + be used as before, and the SASL reports will only be printed + if the SASL application is running - through a second log + handler named sasl_h.

+

All SASL reports have a metadata + field domain=>[beam,erlang,otp,sasl], which can be + used, for example, by filters to to stop or allow the + events.

+
+
+
+ + +
+ Error handling +

Log data is expected to be either a format string and + arguments, a string (unicode:chardata), or a report (map or + key-value list) which can be converted to a format string and + arguments by the handler. A default report callback should be + included in the log event's metadata, which can be used for + converting the report to a format string and arguments. The + handler might also do a custom conversion if the default format + is not desired.

+

logger does, to a certain extent, check its input data + before forwarding a log event to the handlers, but it does not + evaluate conversion funs or check the validity of format strings + and arguments. This means that any filter or handler must be + careful when formatting the data of a log event, making sure + that it does not crash due to bad input data or faulty + callbacks.

+

If a filter or handler still crashes, logger will remove the + filter or handler in question from the configuration, and then + print a short error message on the console. A debug event + containing the crash reason and other details is also issued, + and can be seen if a handler is installed which logs on debug + level.

+
+ +
+ Example: add a handler to log debug events to file +

When starting an erlang node, the default behavior is that all + log events with level info and above are logged to the + console. In order to also log debug events, you can either + change the global log level to debug or add a separate + handler to take care of this. In this example we will add a new + handler which prints the debug events to a separate file.

+

First, we add an instance of logger_std_h with + type {file,File}, and we set the handler's level + to debug:

+
+1> Config = #{level=>debug,logger_std_h=>#{type=>{file,"./debug.log"}}}.
+#{logger_std_h => #{type => {file,"./debug.log"}},
+  level => debug}
+2> logger:add_handler(debug_handler,logger_std_h,Config).
+ok
+

By default, the handler receives all events, so we need to add a filter + to stop all non-debug events:

+
+3> Fun = fun(#{level:=debug}=Log,_) -> Log; (_,_) -> stop end.
+#Fun<erl_eval.12.98642416>
+4> logger:add_handler_filter(debug_handler,allow_debug,{Fun,[]}).
+ok
+

And finally, we need to make sure that the logger itself allows + debug events. This can either be done by setting the global + logger level:

+
+5> logger:set_logger_config(level,debug).
+ok
+

Or by allowing debug events from one or a few modules only:

+
+6> logger:set_module_level(mymodule,debug).
+ok
+ +
+ +
+ Example: implement a handler +

The only requirement that a handler MUST fulfill is to export + the following function:

+ log(logger:log(),logger:config()) ->ok +

It may also implement the following callbacks:

+ +adding_handler(logger:handler_id(),logger:config()) -> {ok,logger:config()} | {error,term()} +removing_handler(logger:handler_id()) -> ok +changing_config(logger:handler_id(),logger:config(),logger:config()) -> {ok,logger:config()} | {error,term()} + +

When logger:add_handler(Id,Module,Config) is called, logger + will first call Module:adding_handler(Id,Config), and if it + returns {ok,NewConfig} the NewConfig is written to the + configuration database. After this, the handler may receive log + events as calls to Module:log/2.

+

A handler can be removed by calling + logger:remove_handler(Id). logger will call + Module:removing_handler(Id), and then remove the handler's + configuration from the configuration database.

+

When logger:set_handler_config is called, logger calls + Module:changing_config(Id,OldConfig,NewConfig). If this function + returns ok, the NewConfig is written to the configuration + database.

+ +

A simple handler which prints to the console could be + implemented as follows:

+ +-module(myhandler). +-export([log/2]). + +log(#{msg:={report,R}},_) -> + io:format("~p~n",[R]); +log(#{msg:={string,S}},_) -> + io:put_chars(S); +log(#{msg:={F,A}},_) -> + io:format(F,A). + + +

A simple handler which prints to file could be implemented like + this:

+ +-module(myhandler). +-export([adding_handler/2, removing_handler/1, log/2]). +-export([init/1, handle_call/3, handle_cast/2, terminate/2]). + +adding_handler(Id,Config) -> + {ok,Fd} = file:open(File,[append,{encoding,utf8}]), + {ok,Config#{myhandler_fd=>Fd}}. + +removing_handler(Id,#{myhandler_fd:=Fd}) -> + _ = file:close(Fd), + ok. + +log(#{msg:={report,R}},#{myhandler_fd:=Fd}) -> + io:format(Fd,"~p~n",[R]); +log(#{msg:={string,S}},#{myhandler_fd:=Fd}) -> + io:put_chars(Fd,S); +log(#{msg:={F,A}},#{myhandler_fd:=Fd}) -> + io:format(Fd,F,A). + + +

Note that none of the above handlers have any overload + protection, and all log events are printed directly from the + client process. Neither do the handlers use the formatter or + in any way add time or other metadata to the printed events.

+ +

For examples of overload protection, please refer to the + implementation + of logger_std_h + and logger_disk_log_h + .

+ +

Below is a simpler example of a handler which logs through one + single process, and uses the default formatter to gain a common + look of the log events.

+

It also uses the metadata field report_cb, if it exists, + to print reports in the way the event issuer suggests. The + formatter will normally do this, but if the handler either has + an own default (as in this example) or if the + given report_cb should not be used at all, then the + handler must take care of this itself.

+ +-module(myhandler). +-export([adding_handler/2, removing_handler/1, log/2]). +-export([init/1, handle_call/3, handle_cast/2, terminate/2]). + +adding_handler(Id,Config) -> + {ok,Pid} = gen_server:start(?MODULE,Config), + {ok,Config#{myhandler_pid=>Pid}}. + +removing_handler(Id,#{myhandler_pid:=Pid}) -> + gen_server:stop(Pid). + +log(Log,#{myhandler_pid:=Pid} = Config) -> + gen_server:cast(Pid,{log,Log,Config}). + +init(#{myhandler_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,Log,Config},#{fd:=Fd} = State) -> + do_log(Fd,Log,Config), + {noreply,State}. + +terminate(Reason,#{fd:=Fd}) -> + _ = file:close(Fd), + ok. + +do_log(Fd,#{msg:={report,R}} = Log, Config) -> + Fun = maps:get(report_cb,Config,fun my_report_cb/1, + {F,A} = Fun(R), + do_log(Fd,Log#{msg=>{F,A},Config); +do_log(Fd,Log,#{formatter:={FModule,FConfig}}) -> + String = FModule:format(Log,FConfig), + io:put_chars(Fd,String). + +my_report_cb(R) -> + {"~p",[R]}. + +
+ + +
+ See Also +

error_logger(3), + SASL(6)

+
+
diff --git a/lib/kernel/doc/src/logger_filters.xml b/lib/kernel/doc/src/logger_filters.xml new file mode 100644 index 0000000000..d742391e35 --- /dev/null +++ b/lib/kernel/doc/src/logger_filters.xml @@ -0,0 +1,191 @@ + + + + +
+ + 2018 + Ericsson AB. 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. + 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. + + + + logger_filters + + + + + + + A + logger_filters.xml +
+ logger_filters + Filters to use with logger. + + +

Filters to use with logger. All functions exported from this + module can be used as logger or handler + filters. See + logger:add_logger_filter/2 + and + logger:add_handler_filter/3 + for more information about how filters are added.

+
+ + + + + Filter log events based on the domain field in metadata. + +

This filter provides a way of filtering log events based on a + domain field Metadata.

+ +

The Extra parameter is specified when + adding the filter + via + logger:add_logger_filter/2 + or + logger:add_handler_filter/3.

+ +

The filter compares the value of the domain field + in the log event's metadata (Domain) + to MatchDomain as follows:

+ + + Compare = starts_with +

The filter matches if MatchDomain is a prefix + of Domain.

+ Compare = prefix_of +

The filter matches if Domain is a prefix + of MatchDomain.

+ Compare = equals +

The filter matches if Domain is equal + to MatchDomain.

+ Compare = no_domain +

The filter matches if there is no domain field in + metadata. In this case MatchDomain shall + be [].

+
+ +

If the filter matches and Action = + log, the log event is allowed. If the filter matches + and Action = stop, the log event is + stopped.

+ +

If the filter does not match, it returns ignore, + meaning that other filters, or the value of the + configuration parameter filter_default, will decide + if the event is allowed or not.

+ +

Log events that do not contain any domain field, will + only match when Compare = no_domain.

+ +

Example: stop all events with + domain [beam,erlang,otp,sasl|_]

+ + +logger:set_handler_config(h1,filter_default,log). % this is the default +Filter = {fun logger_filters:domain/2,{stop,starts_with,[beam,erlang,otp,sasl]}}. +logger:add_handler_filter(h1,no_sasl,Filter). +ok +
+
+ + + + Filter log events based on the log level. + +

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 predefined MatchLevel

+ +

The Extra parameter is specified when + adding the filter + via + logger:add_logger_filter/2 + or + logger:add_handler_filter/3.

+ +

The filter compares the value of the event's log level + (Level) to MatchLevel by + calling + logger:compare_levels(Level,MatchLevel) -> CmpRet. It + matches the event if:

+ + + CmpRet = eq and Operator = + eq | lteq | gteq + CmpRet = lt and Operator = + lt | lteq | neq + CmpRet = gt and Operator = + gt | gteq | neq + + +

If the filter matches and Action = + log, the log event is allowed. If the filter matches + and Action = stop, the log event is + stopped.

+ +

If the filter does not match, it returns ignore, + meaning that other filters, or the value of the + configuration parameter filter_default, will decide + if the event is allowed or not.

+ +

Example: only allow debug level log events

+ + +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 +
+
+ + + + Filter progress reports from supervisor and application_controller. + +

This filter matches all progress reports + from supervisor and application_controller.

+ +

If Extra = log, the progress reports + are allowed. If Extra = stop, the + progress reports are stopped.

+ +

The filter returns ignore for all other log events.

+
+
+ + + + Filter events with group leader on remote node. + +

This filter matches all events originating from a process + that has its group leader on a remote node.

+ +

If Extra = log, the matching events + are allowed. If Extra = stop, the + matching events are stopped.

+ +

The filter returns ignore for all other log events.

+
+
+ +
+ +
+ + diff --git a/lib/kernel/doc/src/logger_formatter.xml b/lib/kernel/doc/src/logger_formatter.xml new file mode 100644 index 0000000000..213a592e47 --- /dev/null +++ b/lib/kernel/doc/src/logger_formatter.xml @@ -0,0 +1,149 @@ + + + + +
+ + 2017 + Ericsson AB. 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. + 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. + + + + logger_formatter + + + + + + + A + logger_formatter.xml +
+ logger_formatter + Default formatter for the Logger application. + + +

Default formatter for the Logger application.

+
+ + + + + + + + + + + + + Formats the given message. + +

Formats the given message.

+

The template is a list of atoms, tuples and strings. Atoms + can be level or msg, which are placeholders + for the severity level and the log message, + repectively. Tuples are interpreted as placeholders for + metadata. Each element in the tuple must be an atom which + matches a key in the nested metadata map, e.g. the + tuple {key1,key2} will be replaced by the value of + the key2 field in this nested map (the value vill be + converted to a string):

+ + +#{key1=>#{key2=>my_value, + ...}, + ...} + + +

Strings are printed literally.

+ +

depth is 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 + io:format/2 + in STDLIB.

+ +

max_size is a positive integer representing the + maximum size a string returned from this formatter can + have. If the formatted string is longer, it will be + truncated.

+ +

utc is a boolean. If set to true, all dates are + displayed in Universal Coordinated Time. Default + is false.

+ +

report_cb must be a function with arity 1, + returning {Format,Args}. This function will replace + any report_cb found in metadata.

+ +

If single_line=true, all newlines in the message are + replaced with ", ", and whitespaces following directly + after newlines are removed. Note that newlines added by the + formatter template are not replaced.

+ +

If legacy_header=true a header field is added to + logger_formatter's part of Metadata. The value of + this field is a string similar to the header created by the + old error_logger event handlers. It can be included + in the log event by adding the + tuple {logger_formatter,header} to the template.

+ +

The default template when legacy_header=true is

+ + [{logger_formatter,header},"\n",msg,"\n"] + +

which will cause log entries like this:

+ + =ERROR REPORT==== 29-Dec-2017::13:30:51.245123 === + process: <0.74.0> + exit_reason: "Something went wrong" + +

Note that all eight levels might occur here, not + only ERROR, WARNING or INFO. And also + that micro seconds are added at the end of the + timestamp.

+ +

The default template when single_line=true is

+ + [time," ",level,": ",msg,"\n"] + +

which will cause log entries like this:

+ + 2017-12-29 13:31:49.640317 error: process: <0.74.0>, exit_reason: "Something went wrong" + +

The default template when both legacy_header and + single_line are set to false is:

+ + [time," ",level,":\n",msg,"\n"] + +

which will cause log entries like this:

+ + 2017-12-29 13:32:25.191925 error: + process: <0.74.0> + exit_reason: "Something went wrong" + +
+
+ +
+ +
+ + 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..2a368b16eb --- /dev/null +++ b/lib/kernel/doc/src/logger_std_h.xml @@ -0,0 +1,81 @@ + + + + +
+ + 2017 + Ericsson AB. 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. + 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. + + + + logger_std_h + + + + + + + A + logger_std_h.xml +
+ logger_std_h + Default handler for the Logger application. + + +

This is the default handler for the Logger + application. Multiple instances of this handler can be added to + logger, and each instance will print logs to standard_io, + standard_error or to a file.

+ +

To add a new instance, + use logger:add_handler/3 + .

+ +

The handler configuration may contain the following keys, + associated with values as described:

+ + filters + +

A list of {Id,{Fun,Args}}, each representing a filter + that may selct or modify log events to forward to this + handler.

+ filter_default + +

The atom log or stop, specifying what to + do with a log event if all filters + return ignore.

+ formatter + +

{Module,Extra}, + where Module:format(Log,Extra) will be called by + the handler to produce the string that will be printed to + the handler's destination.

+ level + +

The level of log events that logger shall forward to + this handler. Log events of the specified, or more severe + levels, are forwarded.

+
+ +
+ + + +
+ + diff --git a/lib/kernel/doc/src/part.xml b/lib/kernel/doc/src/part.xml new file mode 100644 index 0000000000..68eb4530e2 --- /dev/null +++ b/lib/kernel/doc/src/part.xml @@ -0,0 +1,40 @@ + + + + +
+ + 19962017 + Ericsson AB. 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. + 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. + + + + Logger User's Guide + OTP Team + + 2017-12-01 + 0.1 + part.xml +
+ +

The System Architecture Support Libraries SASL application + provides support for alarm handling, release handling, and + related functions.

+
+ + +
+ diff --git a/lib/kernel/doc/src/ref_man.xml b/lib/kernel/doc/src/ref_man.xml index 5cd77e0f6f..7f4d5b384f 100644 --- a/lib/kernel/doc/src/ref_man.xml +++ b/lib/kernel/doc/src/ref_man.xml @@ -52,6 +52,10 @@ + + + + diff --git a/lib/kernel/doc/src/specs.xml b/lib/kernel/doc/src/specs.xml index 29d52f23bb..a67e26ef16 100644 --- a/lib/kernel/doc/src/specs.xml +++ b/lib/kernel/doc/src/specs.xml @@ -20,6 +20,10 @@ + + + + -- cgit v1.2.3