From e484181ecc5c3e2928d10632138837eba3c3229e Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Sun, 20 May 2018 09:21:10 +0200 Subject: Update Logger documentation --- lib/kernel/doc/src/logger.xml | 140 +++++---- lib/kernel/doc/src/logger_arch.png | Bin 31459 -> 32377 bytes lib/kernel/doc/src/logger_chapter.xml | 535 ++++++++++++++++++++-------------- lib/kernel/src/logger.erl | 10 +- 4 files changed, 419 insertions(+), 266 deletions(-) diff --git a/lib/kernel/doc/src/logger.xml b/lib/kernel/doc/src/logger.xml index 13d3e182d4..e2f3dd6e83 100644 --- a/lib/kernel/doc/src/logger.xml +++ b/lib/kernel/doc/src/logger.xml @@ -36,33 +36,6 @@ API module for logging in Erlang/OTP. - - - - -

This module is the main API for logging in Erlang/OTP. It contains functions that allow applications to use a single log @@ -217,6 +190,15 @@ logger:error("error happened because: ~p",[Reason]). %% Without macro erlang:system_time(microsecond).

+ + + +

Configuration data for the + formatter. See + logger_formatter(3) + for an example of a formatter implementation.

+
+
@@ -486,8 +468,8 @@ Current logger configuration: handler part.

-

See section - Filter in the User's Guide for more information +

See section + Filters in the User's Guide for more information about filters.

Some built-in filters exist. These are defined in logger_filters.

@@ -528,7 +510,7 @@ Current logger configuration:

See - section Filter + section Filters in the User's Guide for more information about filters.

Some built-in filters exist. These are defined in logger_filters.

@@ -891,14 +873,15 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(),Meta)).
- Callback Functions + + Handler Callback Functions

The following functions are to be exported from a handler callback module.

- Module:adding_handler(HandlerId,Config1) -> {ok,Config2} | {error,Reason} + HModule:adding_handler(HandlerId,Config1) -> {ok,Config2} | {error,Reason} An instance of this handler is about to be added. HandlerId = @@ -911,7 +894,7 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(),Meta)).

This callback function is optional.

The function is called when an new handler is about to be added, and the purpose is to verify the configuration and - initiate all resourced needed by the handler.

+ initiate all resources needed by the handler.

If everything succeeds, the callback function can add possible default values or internal state values to the configuration, and return the adjusted map @@ -922,24 +905,7 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(),Meta)). - Module:removing_handler(HandlerId,Config) -> ok - The given handler is about to be removed. - - HandlerId = - handler_id() - Config = - config() - - -

This callback function is optional.

-

The function is called when a handler is about to be - removed, and the purpose is to release all resources used by - the handler. The return value is ignored by Logger.

- -
- - - Module:changing_config(HandlerId,Config1,Config2) -> {ok,Config3} | {error,Reason} + HModule:changing_config(HandlerId,Config1,Config2) -> {ok,Config3} | {error,Reason} The configuration for this handler is about to change. HandlerId = @@ -961,6 +927,78 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(),Meta)). return {error,Reason}.

+ + + HModule:log(Log,Config) -> void() + Log the given log event. + + Log = + log() + Config = + config() + + +

This callback function is mandatory.

+

The function is called when all global filters and all + handler filters for the handler in question have passed for + the given log event.

+

The handler must log the event.

+

The return value from this function is ignored by + Logger.

+
+
+ + + HModule:removing_handler(HandlerId,Config) -> ok + The given handler is about to be removed. + + HandlerId = + handler_id() + Config = + config() + + +

This callback function is optional.

+

The function is called when a handler is about to be + removed, and the purpose is to release all resources used by + the handler. The return value is ignored by Logger.

+
+
+ +
+ +
+ + Formatter Callback Functions +

The following functions are to be exported from a formatter + callback module.

+
+ + + + FModule:format(Log,FConfig) -> FormattedLogEntry + Format the given log event. + + Log = + log() + FConfig = + formatter_config() + FormattedLogEntry = + unicode:chardata() + + +

This callback function is mandatory.

+

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 + io:put_chars/1,2.

+

See + logger_formatter(3) + for an example implementation. logger_formatter is the + default formatter used by Logger.

+
+
diff --git a/lib/kernel/doc/src/logger_arch.png b/lib/kernel/doc/src/logger_arch.png index 727609a6ef..901122193a 100644 Binary files a/lib/kernel/doc/src/logger_arch.png 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 index 522d0ce29d..fd86e9e366 100644 --- a/lib/kernel/doc/src/logger_chapter.xml +++ b/lib/kernel/doc/src/logger_chapter.xml @@ -30,30 +30,44 @@ logger_chapter.xml +

As of OTP-21, Erlang/OTP provides a standard API for logging + through Logger, 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.

+

By default, the Kernel application installs one log handler at + system start. This handler is named default. 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.

+

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 disk_log.

+

By confiugration, you can aslo modify or disable the default + handler, replace it by a custom handler, and install additional + handlers.

+
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 part forwards log events to - one or more handler(s).

+

A log event consists of a log level, the + message to be logged, and metadata.

+

The Logger backend forwards log events from the API, first + through a set of global filters, then through a set + of handler filters for each log handler.

+

Each filter set consists of a log level check, + followed by zero or more filter functions.

+

The following figure show a conseptual overview of Logger. The + figure shows two log handlers, but any number of handlers can be + installed.

- Conceptual overview + Conceptual Overview -

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

- -

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:

+ +

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

@@ -101,148 +115,216 @@ 7 debug-level messages - Severity levels + Log 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 - -

The handler callback is called after filtering on logger - level and on handler level for the handler in - question. The function call is done on the client process, - and it is up to the handler implementation if other - processes are to be involved or not.

- -

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

- -
- - Filter - -

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

- -

A filter is specified as:

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

The configuration parameter filter_default - specifies the behaviour 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,FConfig) -> unicode:chardata() - -

The formatter callback 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

-
+

A log event passes the level check if the integer value of its + log level is less than or equal to the currently configured log + level, that is, if the event is equally or more severe than the + configured level.

+

The global log level can be overridden by a log level + configured per module. This is to, for instance, allow more + verbose logging from a specific part of the system.

+

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 Filters for more + details.

+

If a log event passes through all global filters and all + handler filters for a specific handler, Logger forwards the event + to the handler callback. The handler formats and prints the + event to its destination. See + section Handlers for + more details.

+

Everything upto and including the call to the handler callbacks + is executed on the client process, that is, the process where + the log event was issued. It is up to the handler implementation + if other processes are to be involved or not.

+

The handlers are called in sequence, and the order is not + defined.

+
+
+ + Filters +

Filters can be global, or attached to a specific + handler. Logger calls the global 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.

+

A filter is defined as:

+
{FilterFun, Extra}
+

where FilterFun is a function of arity 2, + and Extra is any term. When applying the filter, Logger + calls the function with the log event as the first argument, + and the value of Extra as the second + argument. See + logger:filter() for type definitions.

+

The filter function can return stop, ignore or + the (possibly modified) log event.

+

If stop is returned, the log event is immediately + discarded. If the filter is global, no handler filters or + callbacks are called. If it is a handler filter, the + corresponding handler callback is not called, but the log event + is forwarded to the filters attached to the next handler, if + any.

+

If the log event is returned, the next filter function is + called with the returned value as the first argument. That is, + if a filter function modifies the log event, the next filter + function receivea the modified event. The value returned from + the last filter funcion is the value that the handler callback + receives.

+

If the filter function returns ignore, it means that it + did not recognize the log event, and thus leaves to other + filters to decide the event's destiny.

+

The configuration + option filter_default + specifies the behaviour if all filter functions + return ignore. filter_default is by default set + to log, meaning that if all filters ignore a log event, + Logger forwards the event to the handler + callback. If filter_default is set to stop, + Logger discards such events.

+ +

Filters are applied in the reverse order of installation, + meaning that the last added filter is applied first.

+ +

Global filters are added + with + logger:add_logger_filter/2 + and removed + with + logger:remove_logger_filter/1. They can also + be added at system start via Kernel configuration + parameter logger.

+

Handler filters are added with + with + logger:add_handler_filter/3 + and removed + with + logger:remove_handler_filter/2. They can also + be specified directly in the configuration when adding a handler + with + logger:add_handler/3 + or via Kernel configuration + parameter logger.

+ +

To see which filters are currently installed in the system, + use logger:i/0, + or + logger:get_logger_config/0 + and + logger:get_handler_config/1. Filters are + applied in the order they are listed.

+ +

For convenience, the following built-in filters exist:

+ + + +

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

+
+ +

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

+
+ +

+ logger_filters:progress/2 stops or allows + progress reports from supervisor + and application_controller.

+
+ +

+ logger_filters:remote_gl/2 stops or allows + log events originating from a process that has its group + leader on a remote node.

+
+
+
- logger_filters:level/2 - -

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

-
+
+ + Handlers +

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

+ +
log(Log, Config)
+ +

This function is called when a log event has passed through all + global filters, and all handler filters attached to the handler + in question. The function call is executed on the client + process, and it is up to the handler implementation if other + processes are to be involved or not.

+ +

Logger allows adding multiple instances of a handler + callback. That is, the callback module might be implemented in + such a way that, by using different handler identities, the same + callback module can be used for multiple handler + instances. Handler configuration is per instance.

+ +

In addition to the mandatory callback function log/2, a + handler module can export the optional callback + functions adding_handler/2, changing_config/3 + and removing_handler/1. See + section Handler + Callback Functions in the logger(3) manual for more + information about these function.

+ +

The following built-in handlers exist:

- logger_filters:progress/2 - -

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

-
+ + 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_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

-
-
-
+ logger_disk_log_h + +

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

+
-
- Default formatter + 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 error_logger + event handler is added + with + error_logger:add_report_handler/1,2.

+ +

The old error_logger event handlers in STDLIB and + SASL still exist, but they are not added by Erlang/OTP.

+
+ +
-

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

-
+
+ + Formatters +

A formatter can be used by the handler implementation to do the + final formatting of a log event, before printing to the + handler's destination. The handler callback gets the formatter + information in the handler configuration, which is passed as the + second argument to + HModule:log/2.

+

The formatter information consits of a formatter + module, FModule and its + configuration, FConfig. FModule must export the + following function, which can be called by the handler:

+
format(Log,FConfig)
+	-> FormattedLogEntry
+

See the + logger_formatter(3) manual for the full + description of the default formatter used by Logger.

@@ -347,101 +429,130 @@
- Logger configuration + Global Logger Configuration - level + level = + logger:level() -

Specifies the severity level to log.

+

Specifies the global log level to log.

+

See table Log + Levels in the Overview section for a listing + and description of possible log levels.

+

The initial value of this option is set by the Kernel + configuration + parameter + logger_level. It can be changed during + runtime + with + logger:set_logger_config(level,NewLevel).

- filters + filters = [{ + logger:filter_id(), + + logger:filter()}] -

Logger filters are added or removed with +

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

-

See Filter for more - information.

-

By default, no filters exist.

+

See section Filters + for more information.

+

Default is [], that is, no filters exist.

- filter_default = log | stop + filter_default = log | stop

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

+

See section Filters + for more information about how this option is used.

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 + Handler Configuration - level + level = + logger:level() -

Specifies the severity level to log.

+

Specifies the log level which the handler logs.

+

See table Log + Levels in the Overview section for a listing + and description of possible log levels.

+

The log level can be specified when adding the handler, + or changed during runtime with, for + instance, + logger:set_handler_config/3.

+

Default is info.

- filters + filters = [{ + logger:filter_id(), + + logger:filter()}]

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

-

See Filter for more +

See Filters for more information.

-

By default, no filters exist.

+

Default is [], that is, no filters exist.

- filter_default = log | stop + filter_default = log | stop

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

+

See section Filters + for more information about how this option is used.

Default is log.

- formatter = {FModule::module(),FConfig::map()} + formatter = {module(), + logger:formatter_config()} -

See Formatter for more +

The formatter which the handler can use for converting + the log event term to a printable string.

+

See Formatters for more information.

-

The default module is - logger_formatter, and FConfig is - it's configuration map.

+

Default + is {logger_formatter,DefaultFormatterConfig}, see + the + logger_formatter(3) + manual for information about this formatter and its + default configuration.

- HandlerConfig, term() = term() + HandlerConfig, atom() = term() - Any keys not listed above are considered to be handler specific - configuration. The configuration of the Kernel handlers can be found in - logger_std_h and - logger_disk_log_h. +

Any keys not listed above are considered to be handler + specific configuration. The configuration of the Kernel + handlers can be found in + the logger_std_h(3) + and + logger_disk_log_h(3) + manual pages.

-

Note that level and filters are obeyed by +

Notice that level and filters are obeyed by Logger itself before forwarding the log events to each - handler, while formatter is left to the handler - implementation. All Logger's built-in handlers will call the - given formatter before printing.

+ handler, while formatter and all handle specific + options are left to the handler implementation.

+

All Logger's built-in handlers will call the given formatter + before printing.

- Backwards compatibility with error_logger + Backwards Compatibility with error_logger

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

@@ -556,15 +667,17 @@ error_logger:add_report_handler/1,2.
- Error handling + Error Handling

Log data is expected to be either a format string and - arguments, a string (unicode:chardata), or a report (map or + 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.

+ arguments by the handler. If a report is given, a default report + callback can be included in the log event's metadata. The + handler can use this callback for converting the report to a + format string and arguments. The handler might also do a custom + conversion if the default format is not desired.

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 @@ -630,17 +743,17 @@ removing_handler(logger:handler_id(),logger:config()) -> 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 + will first call HModule:adding_handler(Id,Config), and if it returns {ok,NewConfig}, NewConfig is written to the configuration database. After this, the handler may receive log - events as calls to Module:log/2.

+ events as calls to HModule:log/2.

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

When logger:set_handler_config/2,3 or logger:update_handler_config/2 are called, Logger - calls Module:changing_config(Id,OldConfig,NewConfig). If + calls HModule:changing_config(Id,OldConfig,NewConfig). If this function returns {ok,NewConfig}, NewConfig is written to the configuration database.

@@ -723,7 +836,7 @@ do_log(Fd,Log,#{formatter:={FModule,FConfig}}) ->
- Protecting the handler from overload + Protecting the Handler from Overload

In order for the built-in handlers to survive, and stay responsive, during periods of high load (i.e. when huge numbers of incoming log requests must be handled), a mechanism for overload protection @@ -734,7 +847,7 @@ do_log(Fd,Log,#{formatter:={FModule,FConfig}}) -> as follows:

- Message queue length + Message Queue Length

The handler process keeps track of the length of its message queue and reacts in different ways depending on the current status. The purpose is to keep the handler in, or (as quickly as possible), @@ -829,7 +942,7 @@ logger:add_handler(my_standard_h, logger_std_h,

- Controlling bursts of log requests + Controlling Bursts of Log Requests

A potential problem with large bursts of log requests, is that log files may get full or wrapped too quickly (in the latter case overwriting previously logged data that could be of great importance). For this reason, @@ -870,7 +983,7 @@ logger:add_handler(my_disk_log_h, logger_disk_log_h,

- Terminating a large handler + Terminating a Large Handler

A handler process may grow large even if it can manage peaks of high load without crashing. The overload protection mechanism includes user configurable levels for a maximum allowed message queue length and maximum allowed memory diff --git a/lib/kernel/src/logger.erl b/lib/kernel/src/logger.erl index 2a0e2e5f50..9c721d7fee 100644 --- a/lib/kernel/src/logger.erl +++ b/lib/kernel/src/logger.erl @@ -93,14 +93,16 @@ -type config() :: #{level => level(), filter_default => log | stop, filters => [{filter_id(),filter()}], - formatter => {module(),map()}, - term() => term()}. + formatter => {module(),formatter_config()}, + atom() => term()}. -type timestamp() :: integer(). +-type formatter_config() :: #{atom() => term()}. -type config_handler() :: {handler, handler_id(), module(), config()}. -export_type([log/0,level/0,report/0,msg_fun/0,metadata/0,config/0,handler_id/0, - filter_id/0,filter/0,filter_arg/0,filter_return/0, config_handler/0]). + filter_id/0,filter/0,filter_arg/0,filter_return/0,config_handler/0, + formatter_config/0]). %%%----------------------------------------------------------------- %%% API @@ -390,7 +392,7 @@ get_handler_config(HandlerId) -> -spec update_formatter_config(HandlerId,FormatterConfig) -> ok | {error,term()} when HandlerId :: config(), - FormatterConfig :: map(). + FormatterConfig :: formatter_config(). update_formatter_config(HandlerId,FormatterConfig) -> logger_server:update_formatter_config(HandlerId,FormatterConfig). -- cgit v1.2.3