From 8aa64c90ddd20ec0ca8cc5fe92a6124324c51da5 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Wed, 16 May 2018 16:10:30 +0200 Subject: Use system_time instead of monotonic_time as timestamp in logger --- lib/kernel/doc/src/logger.xml | 6 +++--- lib/kernel/src/code_server.erl | 4 ++-- lib/kernel/src/logger.erl | 2 +- lib/kernel/src/logger_formatter.erl | 11 +++++------ lib/kernel/src/logger_simple.erl | 7 +++---- lib/kernel/test/logger_SUITE.erl | 4 ++-- lib/kernel/test/logger_formatter_SUITE.erl | 5 ++--- 7 files changed, 18 insertions(+), 21 deletions(-) (limited to 'lib') diff --git a/lib/kernel/doc/src/logger.xml b/lib/kernel/doc/src/logger.xml index 183102f240..cac9c39f2a 100644 --- a/lib/kernel/doc/src/logger.xml +++ b/lib/kernel/doc/src/logger.xml @@ -111,7 +111,7 @@ logger:error("error happened because: ~p",[Reason]). %% Without macro pid => self() gl => group_leader() - time => erlang:monotonic_time(microsecond) + time => erlang:system_time(microsecond)

When a log macro is used, Logger also inserts location information:

@@ -184,8 +184,8 @@ logger:error("error happened because: ~p",[Reason]). %% Without macro

A timestamp produced - with - erlang:monotonic_time(microsecond).

+ with + erlang:system_time(microsecond).

diff --git a/lib/kernel/src/code_server.erl b/lib/kernel/src/code_server.erl index bbfa2a995d..1a7677295b 100644 --- a/lib/kernel/src/code_server.erl +++ b/lib/kernel/src/code_server.erl @@ -1437,7 +1437,7 @@ error_msg(Format, Args) -> logger ! {log,error,Format,Args, #{pid=>self(), gl=>group_leader(), - time=>erlang:monotonic_time(microsecond), + time=>erlang:system_time(microsecond), error_logger=>#{tag=>error}}}, ok. @@ -1446,7 +1446,7 @@ info_msg(Format, Args) -> logger ! {log,info,Format,Args, #{pid=>self(), gl=>group_leader(), - time=>erlang:monotonic_time(microsecond), + time=>erlang:system_time(microsecond), error_logger=>#{tag=>info_msg}}}, ok. diff --git a/lib/kernel/src/logger.erl b/lib/kernel/src/logger.erl index a839f97e62..281521ae6e 100644 --- a/lib/kernel/src/logger.erl +++ b/lib/kernel/src/logger.erl @@ -833,7 +833,7 @@ proc_meta() -> default(pid) -> self(); default(gl) -> group_leader(); -default(time) -> erlang:monotonic_time(microsecond). +default(time) -> erlang:system_time(microsecond). %% Remove everything upto and including this module from the stacktrace filter_stacktrace(Module,[{Module,_,_,_}|_]) -> diff --git a/lib/kernel/src/logger_formatter.erl b/lib/kernel/src/logger_formatter.erl index 602c666cc7..a19e7bbc73 100644 --- a/lib/kernel/src/logger_formatter.erl +++ b/lib/kernel/src/logger_formatter.erl @@ -197,16 +197,15 @@ truncate(String,Size) -> String end. -format_time(Timestamp,#{time_offset:=Offset,time_designator:=Des}) - when is_integer(Timestamp) -> - SysTime = Timestamp + erlang:time_offset(microsecond), +%% SysTime is the system time in microseconds +format_time(SysTime,#{time_offset:=Offset,time_designator:=Des}) + when is_integer(SysTime) -> calendar:system_time_to_rfc3339(SysTime,[{unit,microsecond}, {offset,Offset}, {time_designator,Des}]). -%% Assuming this is monotonic time in microseconds -timestamp_to_datetimemicro(Timestamp,Config) when is_integer(Timestamp) -> - SysTime = Timestamp + erlang:time_offset(microsecond), +%% SysTime is the system time in microseconds +timestamp_to_datetimemicro(SysTime,Config) when is_integer(SysTime) -> Micro = SysTime rem 1000000, Sec = SysTime div 1000000, UniversalTime = erlang:posixtime_to_universaltime(Sec), diff --git a/lib/kernel/src/logger_simple.erl b/lib/kernel/src/logger_simple.erl index 5272455a2d..c8cdf25887 100644 --- a/lib/kernel/src/logger_simple.erl +++ b/lib/kernel/src/logger_simple.erl @@ -70,7 +70,7 @@ log(#{msg:=_,meta:=#{time:=_}}=Log,_Config) -> do_log( #{level=>error, msg=>{report,{error,simple_handler_process_dead}}, - meta=>#{time=>erlang:monotonic_time(microsecond)}}), + meta=>#{time=>erlang:system_time(microsecond)}}), do_log(Log); _ -> ?MODULE ! {log,Log} @@ -126,7 +126,7 @@ drop_msg(0) -> drop_msg(N) -> [#{level=>info, msg=>{"Simple handler buffer full, dropped ~w messages",[N]}, - meta=>#{time=>erlang:monotonic_time(microsecond)}}]. + meta=>#{time=>erlang:system_time(microsecond)}}]. %%%----------------------------------------------------------------- %%% Internal @@ -141,8 +141,7 @@ do_log(#{msg:=Msg,meta:=#{time:=T}}) -> display_date(T), display(Msg). -display_date(Timestamp0) when is_integer(Timestamp0) -> - Timestamp = Timestamp0 + erlang:time_offset(microsecond), +display_date(Timestamp) when is_integer(Timestamp) -> Micro = Timestamp rem 1000000, Sec = Timestamp div 1000000, {{Y,Mo,D},{H,Mi,S}} = erlang:universaltime_to_localtime( diff --git a/lib/kernel/test/logger_SUITE.erl b/lib/kernel/test/logger_SUITE.erl index e602fa2576..1d3410e356 100644 --- a/lib/kernel/test/logger_SUITE.erl +++ b/lib/kernel/test/logger_SUITE.erl @@ -769,14 +769,14 @@ process_metadata(_Config) -> undefined = logger:get_process_metadata(), {error,badarg} = ?TRY(logger:set_process_metadata(bad)), ok = logger:add_handler(h1,?MODULE,#{level=>info,filter_default=>log}), - Time = erlang:monotonic_time(microsecond), + Time = erlang:system_time(microsecond), ProcMeta = #{time=>Time,line=>0,custom=>proc}, ok = logger:set_process_metadata(ProcMeta), S1 = ?str, ?LOG_INFO(S1,#{custom=>macro}), check_logged(info,S1,#{time=>Time,line=>0,custom=>macro}), - Time2 = erlang:monotonic_time(microsecond), + Time2 = erlang:system_time(microsecond), S2 = ?str, ?LOG_INFO(S2,#{time=>Time2,line=>1,custom=>macro}), check_logged(info,S2,#{time=>Time2,line=>1,custom=>macro}), diff --git a/lib/kernel/test/logger_formatter_SUITE.erl b/lib/kernel/test/logger_formatter_SUITE.erl index 9baadfd65a..c171165944 100644 --- a/lib/kernel/test/logger_formatter_SUITE.erl +++ b/lib/kernel/test/logger_formatter_SUITE.erl @@ -546,8 +546,7 @@ default_time_format(Timestamp) -> default_time_format(Timestamp,Utc) -> default_time_format(Timestamp,Utc,$T). -default_time_format(Timestamp0,Utc,Sep) -> - Timestamp=Timestamp0+erlang:time_offset(microsecond), +default_time_format(Timestamp,Utc,Sep) -> Offset = if Utc -> "Z"; true -> "" end, @@ -569,7 +568,7 @@ my_try(Fun) -> try Fun() catch C:R:S -> {C,R,hd(S)} end. timestamp() -> - erlang:monotonic_time(microsecond). + erlang:system_time(microsecond). %% necessary? add_time(#{time:=_}=Meta) -> -- cgit v1.2.3 From a9a6b803a60793d42a74e0f1693a7594dffb6bc3 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Thu, 17 May 2018 18:19:57 +0200 Subject: Improve documentation of logger and error_logger --- lib/common_test/doc/src/ct_hooks_chapter.xml | 9 +- lib/kernel/doc/src/error_logger.xml | 48 +++--- lib/kernel/doc/src/introduction_chapter.xml | 1 - lib/kernel/doc/src/kernel_app.xml | 11 +- lib/kernel/doc/src/logger.xml | 184 +++++++++++++--------- lib/kernel/doc/src/logger_chapter.xml | 222 ++++++++++++++++----------- lib/kernel/doc/src/logger_disk_log_h.xml | 22 ++- lib/kernel/doc/src/logger_formatter.xml | 40 +++-- lib/kernel/doc/src/logger_std_h.xml | 19 ++- lib/runtime_tools/doc/src/LTTng.xml | 2 +- lib/sasl/doc/src/error_logging.xml | 52 +++++-- lib/sasl/doc/src/sasl_app.xml | 9 +- lib/stdlib/doc/src/gen_event.xml | 3 +- lib/stdlib/doc/src/gen_server.xml | 6 +- lib/stdlib/doc/src/gen_statem.xml | 4 +- lib/stdlib/doc/src/proc_lib.xml | 50 ++++-- 16 files changed, 416 insertions(+), 266 deletions(-) (limited to 'lib') diff --git a/lib/common_test/doc/src/ct_hooks_chapter.xml b/lib/common_test/doc/src/ct_hooks_chapter.xml index 7ecc2e4298..3957c0f4a5 100644 --- a/lib/common_test/doc/src/ct_hooks_chapter.xml +++ b/lib/common_test/doc/src/ct_hooks_chapter.xml @@ -501,12 +501,13 @@ cth_log_redirect

Built-in

-

Captures all error_logger and SASL logging - events and prints them to the current test case log. If an event cannot be - associated with a test case, it is printed in the Common Test framework log. +

Captures all log events that would normally be printed by the default + logger handler, and prints them to the current test case log. + If an event cannot be associated with a test case, it is printed in + the Common Test framework log. This happens for test cases running in parallel and events occuring in-between test cases. You can configure the level of - SASL events report + SASL reports using the normal SASL mechanisms.

cth_surefire diff --git a/lib/kernel/doc/src/error_logger.xml b/lib/kernel/doc/src/error_logger.xml index c9fe9484e4..e91fc734a4 100644 --- a/lib/kernel/doc/src/error_logger.xml +++ b/lib/kernel/doc/src/error_logger.xml @@ -36,41 +36,31 @@

In OTP-21, a new API for logging was added to Erlang/OTP. The old error_logger module can still be used by legacy code, but new code should use the new API instead.

+

error_logger is no longer started by default, but is + automatically started when an event handler is added + with error_logger:add_report_handler/1,2. The error_logger + module is then also added as a handler to the new logger.

See logger(3) and the Logging chapter - in the user's guide for more information.

+ in the User's Guide for more information.

The Erlang error logger is an event manager (see OTP Design Principles and gen_event(3)), - registered as error_logger. 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 P is - logged at the node of the group leader of P. 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.

-

Initially, error_logger has only a primitive event - handler, which buffers and prints the raw event messages. During - system startup, the Kernel application replaces this with a - standard event handler, 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 kernel(6).

-

Also the SASL application, if started, adds its own event - handler, which by default writes supervisor, crash, and progress - reports to the terminal. See - sasl(6).

-

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 - add_report_handler/1,2. - Also, a useful event handler is provided in STDLIB for multi-file - logging of events, see - log_mf_h(3).

+ registered as error_logger.

+

Error logger is no longer started by default, but is + automatically started when an event handler is added + with + add_report_handler/1,2. The error_logger + 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.

+

User-defined event handlers can be added to handle application-specific + events.

+

Existing event handlers provided by STDLIB and SASL are still + available, but are no longer used by OTP.

Warning events were introduced in Erlang/OTP R9C and are enabled by default as from Erlang/OTP 18.0. To retain backwards compatibility with existing user-defined event handlers, the warning events can be @@ -191,7 +181,7 @@ ok

The error_logger_format_depth variable is deprecated since - the Logger API was + the logging API was introduced in OTP-21. The variable, and this function, are kept for backwards compatibility since they still might be used by legacy report handlers.

diff --git a/lib/kernel/doc/src/introduction_chapter.xml b/lib/kernel/doc/src/introduction_chapter.xml index 6e6990ddda..2eadc70abf 100644 --- a/lib/kernel/doc/src/introduction_chapter.xml +++ b/lib/kernel/doc/src/introduction_chapter.xml @@ -46,7 +46,6 @@ Start, stop, supervision, configuration, and distribution of applications Code loading Logging - Error logging Global name service Supervision of Erlang/OTP Communication with sockets diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml index 7cd05dab14..5bc423afb6 100644 --- a/lib/kernel/doc/src/kernel_app.xml +++ b/lib/kernel/doc/src/kernel_app.xml @@ -42,7 +42,6 @@ Start, stop, supervision, configuration, and distribution of applications Code loading Logging - Error logging Global name service Supervision of Erlang/OTP Communication with sockets @@ -194,9 +193,9 @@ If the SASL application is started, these log events will be sent to a second handler instance named sasl_h, according to values of the SASL - environment variables sasl_error_logger + configuration parameter sasl_error_logger and sasl_errlog_type, see - SASL(6) + sasl(6)

The default value is false.

See chapter Backwards @@ -271,7 +270,7 @@ inet_parse_error_log = silent

If set, no - error_logger messages are generated when erroneous + logger messages are generated when erroneous lines are found and skipped in the various Inet configuration files.

@@ -486,7 +485,7 @@ MaxT = TickTime + TickTime / 4 old error_logger event manager, and event handlers running on this manager, will still work, but they are not used by default.

-

The following application environment variables can still be +

The following application configuration parameters can still be set, but they will only be used if the corresponding new logger variables are not set.

@@ -519,12 +518,12 @@ erl -kernel logger '[{handler,default,logger_std_h,#{formatter=>{logger_formatte disk_log(3), erl_boot_server(3), erl_ddll(3), - error_logger(3), file(3), global(3), global_group(3), heart(3), inet(3), + logger(3), net_kernel(3), os(3), pg2(3), diff --git a/lib/kernel/doc/src/logger.xml b/lib/kernel/doc/src/logger.xml index cac9c39f2a..f7e740e90d 100644 --- a/lib/kernel/doc/src/logger.xml +++ b/lib/kernel/doc/src/logger.xml @@ -33,23 +33,51 @@ logger.xml logger - API module for the logger. + API module for logging in Erlang/OTP. + + + + +

- This module is the main logger API. It contains functions that allow - application to use a single log API and the system to manage those log - events independently. To log events the logger - macros should be used. For instance, - to log a new error log event:

+ This module is the main API for logging in Erlang/OTP. It + contains functions that allow applications to use a single log + API and the system to manage those log events independently. Use + the API functions or the log + macros to log events. For instance, + to log a new error event:

?LOG_ERROR("error happened because: ~p",[Reason]). %% With macro logger:error("error happened because: ~p",[Reason]). %% Without macro -

This log event will then be sent to the configured log handlers which - by default means that it will be printed to the console. If you want +

This log event is then sent to the configured log handlers which + by default means that it is be printed to the console. If you want your systems logs to be printed to a file instead of the console you - have to configure the default handler to do so. The simplest way is + must configure the default handler to do so. The simplest way is to include the following in your sys.config.

[{kernel, @@ -63,7 +91,7 @@ logger:error("error happened because: ~p",[Reason]). %% Without macro how to use the API, see the User's Guide. - how to configure logger, + how to configure Logger, see the Configuration section in the User's Guide. the convinience macros in logger.hrl, @@ -129,8 +157,8 @@ logger:error("error happened because: ~p",[Reason]). %% Without macro update_process_metadata/1
.

Logger merges all the metadata maps before forwarding the log event to the handlers. If the same keys occur, values - from the log call overwrites process metadata, which in turn - overwrites values set by Logger.

+ from the log call overwrite process metadata, which in turn + overwrite values set by Logger.

@@ -165,7 +193,8 @@ logger:error("error happened because: ~p",[Reason]). %% Without macro -

A filter which can be installed for logger or for a handler.

+

A filter which can be installed for the logger part of + Logger, or for a handler.

@@ -213,9 +242,9 @@ logger:error("error happened because: ~p",[Reason]). %% Without macro ?LOG_DEBUG(FunOrFormat,Args[,Metadata]) -

All macros expand to a call to logger, where Level is - taken from the macro name, and location data is added. See the - description of +

All macros expand to a call to Logger, where Level is + taken from the macro name, and location data is added to the + metadata. See the description of the metadata() type for more information about the location data.

@@ -335,23 +364,26 @@ logger:error("error happened because: ~p",[Reason]). %% Without macro - Lookup the current configuration for logger. + Look up the current configuration for the logger part + of Logger. -

Lookup the current configuration for logger.

+

Look up the current configuration for the logger part of + Logger.

- Lookup the current configuration for the given handler. + Look up the current configuration for the given + handler. -

Lookup the current configuration for the given handler.

+

Look up the current configuration for the given handler.

- Get all logger configurations + Get all Logger configurations

Same as logger:i(term)

@@ -361,28 +393,28 @@ logger:error("error happened because: ~p",[Reason]). %% Without macro - Get all logger configurations + Get all Logger configurations -

Display or return all current logger configuration.

+

Display or return all current Logger configurations.

Action = string -

Return the pretty printed current logger configuration +

Return the pretty printed current Logger configuration as iodata.

Action = term -

Return the current logger configuration as a term. The - format of this term may change inbetween releases. For a +

Return the current Logger configuration as a term. The + format of this term may change between releases. For a stable format use logger:get_handler_config/1 and - logger:get_logger_config/0. - The same as calling logger:i().

+ logger:get_logger_config/0.

+

The same as calling logger:i().

Action = print -

Pretty print all the current logger configuration to +

Pretty print all the current Logger configuration to standard out. Example:

logger:i(print). Current logger configuration: @@ -423,9 +455,9 @@ Current logger configuration: - Add a filter to the logger. + Add a filter to the logger part of Logger. -

Add a filter to the logger.

+

Add a filter to the logger part of Logger.

The filter fun is called with the log event as the first parameter, and the specified filter_args() as the second parameter.

@@ -436,8 +468,8 @@ Current logger configuration:

The filter passed. The next logger filter, if any, is applied. If no more logger filters exist, the - log event is forwarded to the handler part of the - logger, where handler filters are applied.

+ log event is forwarded to the handler part of Logger, + where handler filters are applied.

stop @@ -449,9 +481,9 @@ Current logger configuration:

The filter has no knowledge of the log event. The next logger filter, if any, is applied. If no more logger filters exist, the value of the filter_default - configuration parameter for the logger specifies if the - log event shall be discarded or forwarded to the handler - part.

+ configuration parameter for the logger part specifies if + the log event shall be discarded or forwarded to the + handler part.

See section @@ -505,10 +537,10 @@ Current logger configuration: - Remove a filter from the logger. + Remove a filter from the logger part of Logger.

Remove the filter identified - by FilterId from the logger.

+ by FilterId from the logger part of Logger.

@@ -548,21 +580,21 @@ Current logger configuration:

Set the log level for the specified Module.

The log level for a module overrides the global log level - of the logger for log event originating from the module in + of Logger for log events originating from the module in question. Notice, however, that it does not override the level configuration for any handler.

-

For example: Assume that the global log level for the - logger is info, and there is one handler, h1, - with level info and one handler, h2, with +

For example: Assume that the global log level for Logger + is info, and there is one handler, h1, with + level info and one handler, h2, with level debug.

With this configuration, no debug messages will be logged, since they are all stopped by the global log level.

-

If the level for mymodule is set now set +

If the level for mymodule is now set to debug, then debug events from this module will be logged by the handler h2, but not by handler h1.

Debug events from other modules are still not logged.

-

To change the global log level for the logger, use +

To change the global log level for Logger, use logger:set_logger_config(level,Level).

To change the log level for a handler, use @@ -572,9 +604,10 @@ Current logger configuration:

The originating module for a log event is only detected if mfa=>{Module,Function,Arity} exists in the metadata. When log macros are used, this association is - automatically added to all log events. If the logger API + automatically added to all log events. If an API function is called directly, without using a macro, the logging - client must explicitly add this information.

+ client must explicitly add this information if module + levels shall have any effect.

@@ -590,10 +623,11 @@ Current logger configuration: - Setup logger handlers from the applications configuration parameters. + Set up log handlers from the application's + configuration parameters.

Reads the application configuration parameter logger and - calls logger:add_handlers/1 with it contents.

+ calls logger:add_handlers/1 with its contents.

@@ -602,11 +636,12 @@ Current logger configuration: Setup logger handlers. -

This function should be used by custom logger handlers to make +

This function should be used by custom Logger handlers to make configuration consistent no matter which handler the system uses. - Normal usage to to add a call to logger:add_handlers/1 - just after the processes that the handler needs are started - and pass the applications logger config as an argument. Eg.

+ Normal usage is to add a call to logger:add_handlers/1 + just after the processes that the handler needs are started, + and pass the application's logger configuration as the argument. + For example:

-behaviour(application). start(_, []) -> @@ -616,19 +651,20 @@ start(_, []) -> {ok, Pid, []}; Error -> Error end. -

This will read the logger configuration parameter from - the handler application and start the configured handlers. The contents - of the configuration use the same rules as the +

This reads the logger configuration parameter from + the my_all application and starts the configured + handlers. The contents of the configuration use the same + rules as the logger handler configuration.

-

If the handler is meant to replace the default handler the kernels - default handlers have to be disabled before the new handler is added. - A sys.config file that disables the kernel handler and adds - a custom handler could looks like this:

+

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 sys.config file that disables the Kernel handler and adds + a custom handler could look like this:

[{kernel, [{logger, - %% Disable the default kernel handler + %% Disable the default Kernel handler [{handler,default,undefined}]}]}, {my_app, [{logger, @@ -640,10 +676,10 @@ start(_, []) -> - Set configuration data for the logger. + Set configuration data for the logger part of Logger. -

Set configuration data for the logger. This overwrites the - current logger configuration.

+

Set configuration data for the logger part of Logger. This + overwrites the current logger configuration.

To modify the existing configuration, use update_logger_config/1, or, if a more @@ -658,21 +694,25 @@ start(_, []) -> - Add or update configuration data for the logger. + Add or update configuration data for the logger part + of Logger. -

Add or update configuration data for the logger. If the - given Key already exists, its associated - value will be changed to Value. If it - does not exist, it will be added.

+

Add or update configuration data for the logger part of + Logger. If the given Key already exists, + its associated value will be changed + to Value. If it does not exist, it will + be added.

- Update configuration data for the logger. + Update configuration data for the logger part of + Logger. -

Update configuration data for the logger. This function - behaves as if it was implemented as follows:

+

Update configuration data for the logger part of + Logger. This function behaves as if it was implemented as + follows:

{ok,Old} = logger:get_logger_config(), logger:set_logger_config(maps:merge(Old,Config)). @@ -697,7 +737,7 @@ logger:set_logger_config(maps:merge(Old,Config)). , then do the merge before writing the new configuration back with this function.

If a key is removed compared to the current configuration, - and the key is know by Logger, the default value is used. If + and the key is known by Logger, the default value is used. If it is a custom key, then it is up to the handler implementation if the value is removed or a default value is inserted.

diff --git a/lib/kernel/doc/src/logger_chapter.xml b/lib/kernel/doc/src/logger_chapter.xml index 4232429589..21b460e72a 100644 --- a/lib/kernel/doc/src/logger_chapter.xml +++ b/lib/kernel/doc/src/logger_chapter.xml @@ -36,14 +36,14 @@ this API can be used as is, or it can be customized to suite specific needs.

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

+ handler part. The logger part forwards log events to + one or more handler(s).

Conceptual overview -

Filters can be added to the logger and to each +

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.

@@ -121,10 +121,10 @@ 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 +

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 @@ -134,7 +134,7 @@ Filter -

Filters can be set on the logger or on a handler. Logger +

Filters can be set on the logger part, or on a handler. Logger filters are applied first, and if passed, the handler filters for each handler are applied. The handler callback is only called if all handler filters for the handler in question also @@ -145,7 +145,7 @@ {fun((Log,Extra) -> Log | stop | ignore), Extra}

The configuration parameter filter_default - specifies the behavior if all filters return ignore. + 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 @@ -250,52 +250,58 @@

Logger can be configured either when the system starts through configuration parameters, - or at run-time by using the logger + or at run-time by using the logger(3) API. The recommended approach is to do the initial configuration in the sys.config file and then use the API when some configuration - has to be changed at run-time, such as the logging level.

+ has to be changed at run-time, such as the log level.

- Application configuration parameters + Kernel Configuration Parameters

Logger is best configured by using the configuration parameters - of kernel. There are three possible configuration parameters: + of Kernel. There are four possible configuration parameters: logger, logger_level, logger_sasl_compatible and logger_log_progress. - logger_level, logger_sasl_compatible and logger_log_progress are described in the + logger_level, logger_sasl_compatible and logger_log_progress are described in the Kernel Configuration, while logger is described below.

-
+ - logger -

The logger application configuration parameter is used to configure - three different logger aspects; handlers, logger filters and module levels. +

logger

+

The application configuration parameter logger is used to configure + three different Logger aspects; handlers, logger filters and module levels. The configuration is a list containing tagged tuples that look like this:

DisableHandler = {handler,default,undefined} - Disable the default handler. This will allow another application + +

Disable the default handler. This allows another application to add its own default handler. See - logger:add_handlers/1 for more details. + logger:add_handlers/1 for more details.

+

Only one entry of this option is allowed.

AddHandler = {handler,HandlerId,Module,HandlerConfig} - Add a handler as if - logger:add_handler(HandlerId,Module,HandlerConfig) had been - called. - Filters = {filters, FilterDefault, [Filter]}
+ +

Add a handler as if + logger:add_handler(HandlerId,Module,HandlerConfig) is + called.

+

It is allowed to have multiple entries of this option.

+ Filters = {filters, default, [Filter]}
FilterDefault = log | stop
Filter = {FilterId, {FilterFun, FilterConfig}}
- Add the specified - logger filters. Only one entry is allowed of this option. - ModuleLevel - {module_level, Level, [Module]}, - this option configures the - module log level to be used. It is possible to have multiple - module_level entries. + +

Add the specified + logger filters.

+

Only one entry of this option is allowed.

+ ModuleLevel = {module_level, Level, [Module]} + +

This option configures + module log level.

+

It is allowed to have multiple entries of this option.

Examples:

-

Output logs into a the file "logs/erlang.log"

+

Output logs into the file "logs/erlang.log"

[{kernel, [{logger, @@ -338,7 +344,6 @@
-
@@ -441,36 +446,30 @@ 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 + API for Logging

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

+

Calls + to + error_logger:error_report/1,2, + + error_logger:error_msg/1,2, and + corresponding functions for warning and info messages, are + all forwarded to Logger as calls + to + logger:log(Level,Report,Metadata).

+

Level = error | warning | info and is taken + from the function name. Report contains the actual + log message, and Metadata contains additional + information which can be used for creating backwards + compatible events for legacy error_logger event + handlers, see + section Legacy + Event Handlers.

- Output format + Output Format

To get log events on the same format as produced by error_logger_tty_h and error_logger_file_h, @@ -478,13 +477,13 @@ error_logger:add_report_handler/1,2. configuration parameter legacy_header=>true. This is also the default.

- Default format of log events from OTP + 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 + SASL Reports

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

@@ -494,32 +493,63 @@ error_logger:add_report_handler/1,2. 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.

+ SASL + configuration parameters.

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:

+ meaning that the default behaviour 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. + enabled with the Kernel configuration + parameter + 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.

+

If the old behaviour is preferred, the Kernel configuation + parameter + logger_sasl_compatible can be set + to true. The + old SASL + configuration parameters 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 stop or allow the events.

+

See the SASL User's + Guide for more information about the old SASL + error logging functionality.

+ + 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=>[]}. + +

Notice 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 notice that error_logger is not overload + protected.

@@ -535,14 +565,14 @@ error_logger:add_report_handler/1,2. converting the report to a format string and arguments. The handler might also do a custom conversion if the default format is not desired.

-

logger does, to a certain extent, check its input data +

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 +

If a filter or handler still crashes, Logger will remove the filter or handler in question from the configuration, and then print a short error message on the console. A debug event containing the crash reason and other details is also issued, @@ -552,13 +582,13 @@ error_logger:add_report_handler/1,2.

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

When starting an erlang node, the default behavior is that all +

When starting an erlang node, the default behaviour is that all log events with level info and above are logged to the console. In order to also log debug events, you can either change the global log level to 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 +

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

@@ -575,9 +605,9 @@ ok
#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 +

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

+ log level:

 5> logger:set_logger_config(level,debug).
 ok
@@ -599,21 +629,22 @@ adding_handler(logger:handler_id(),logger:config()) -> {ok,logger:config()} | {e removing_handler(logger:handler_id(),logger:config()) -> ok changing_config(logger:handler_id(),logger:config(),logger:config()) -> {ok,logger:config()} | {error,term()}
-

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 +

When logger:add_handler(Id,Module,Config) is called, Logger + will first call Module: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 Module: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 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 + logger:remove_handler(Id). Logger will call + Module: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 + this function returns {ok,NewConfig}, NewConfig is + written to the configuration database.

+ +

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

-module(myhandler). @@ -720,7 +751,7 @@ do_log(Fd,Log,#{formatter:={FModule,FConfig}}) -> and as long as the length of the message queue is lower, all log requests are handled asynchronously. This simply means that the process sending the log request (by calling a log function in the - logger API) does not wait for a response from the handler but + Logger API) does not wait for a response from the handler but continues executing immediately after the request (i.e. it will not be affected by the time it takes the handler to print to the log device). If the message queue grows larger than this value, however, @@ -876,7 +907,14 @@ logger:add_handler(my_disk_log_h, logger_disk_log_h,
See Also -

error_logger(3), - SASL(6)

+

+ disk_log(3), + error_logger(3), + logger(3), + logger_disk_log_h(3), + logger_filters(3), + logger_formatter(3), + logger_std_h(3), + sasl(6)

diff --git a/lib/kernel/doc/src/logger_disk_log_h.xml b/lib/kernel/doc/src/logger_disk_log_h.xml index 440ae28e5d..20b49b8ca0 100644 --- a/lib/kernel/doc/src/logger_disk_log_h.xml +++ b/lib/kernel/doc/src/logger_disk_log_h.xml @@ -33,21 +33,21 @@ logger_disk_log_h.xml logger_disk_log_h - A disk_log based handler for the Logger - application. + A disk_log based handler for the Logger. -

This is a handler for the Logger application that offers circular - (wrapped) logs by using the disk_log application. Multiple instances - of this handler can be added to logger, and each instance will print to +

This is a handler for Logger that offers circular + (wrapped) logs by using disk_log. + 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.

The default standard handler, logger_std_h, can be - replaced by a disk_log handler at startup of the kernel application. + replaced by a disk_log handler at startup of the Kernel application. See an example of this below.

The handler has an overload protection mechanism that will keep the handler - process and the kernel application alive during a high load of log + process and the Kernel application alive during a high load of log requests. How this feature works, and how to modify the configuration, is described in the User's Guide @@ -121,7 +121,7 @@ logger:add_handler(my_disk_log_h, logger_disk_log_h, #{filesync_repeat_interval => 1000}}).

In order to use the disk_log handler instead of the default standard - handler when starting en Erlang node, change the Kernel default logger to + handler when starting an Erlang node, change the Kernel default logger to use disk_log. Example:

erl -kernel logger '[{handler,default,logger_disk_log_h, @@ -141,6 +141,12 @@ erl -kernel logger '[{handler,default,logger_disk_log_h, +
+ See Also +

logger(3)

+

logger_std_h(3)

+

disk_log(3)

+
diff --git a/lib/kernel/doc/src/logger_formatter.xml b/lib/kernel/doc/src/logger_formatter.xml index 370d61d338..ee43634cf9 100644 --- a/lib/kernel/doc/src/logger_formatter.xml +++ b/lib/kernel/doc/src/logger_formatter.xml @@ -39,7 +39,8 @@

Each log handler has a configured formatter specified as a module and a configuration term. The purpose of the formatter is to translate the log events to a final printable string - (unicode:chardata()) which can be written to the output + (unicode:chardata() + ) which can be written to the output device of the handler.

logger_formatter is the default formatter used by Logger.

@@ -47,7 +48,8 @@
Configuration -

The configuration term for logger_formatter is a map, +

The configuration term for logger_formatter is a + map, and the following keys can be set as configuration parameters:

@@ -55,7 +57,7 @@

A positive integer representing the value of the option with the same name to be used when calling - io_lib:format/3. + io_lib:format/3. 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 max_size.

@@ -99,7 +101,7 @@ added by the template parameter are not replaced.

Default is true.

- legacy_header = boolen() + legacy_header = boolean()

If set to true a header field is added to logger_formatter's part of Metadata. The value of @@ -181,8 +183,8 @@ to "+02:00".

The default value is an empty string, meaning that timestamps are displayed in local time. However, for - backwards compatibility, if the SASL environment - variable + backwards compatibility, if the SASL configuration + parameter utc_log=true, the default is changed to "Z", meaning that timestamps are displayed in UTC.

@@ -206,28 +208,42 @@ ?LOG_ERROR("name: ~p~nexit_reason: ~p",[my_name,"It crashed"])
- legacy_header=true + legacy_header=true, single_line=false

Default template: [{logger_formatter,header},"\n",msg,"\n"]

Example log entry:

-2018-05-16T11:55:50.448382+02:00 error: +=ERROR REPORT==== 17-May-2018::18:30:19.453447 === name: my_name exit_reason: "It crashed" -

Notice that all eight levels might occur in the heading, +

Notice that all eight levels can occur in the heading, not only ERROR, WARNING or INFO as the old error_logger produced. And microseconds are added at the end of the timestamp.

- single_line=true + legacy_header=true, single_line=true + +

Default template: [{logger_formatter,header},"\n",msg,"\n"]

+ +

Notice that the template is here the same as + for single_line=false, but the resulting log entry + differs in that there is only one line after the + heading:

+ +=ERROR REPORT==== 17-May-2018::18:31:06.952665 === +name: my_name, exit_reason: "It crashed" +
+ + legacy_header=false, single_line=true

Default template: [time," ",level,": ",msg,"\n"]

Example log entry:

- 2018-05-16T11:55:50.448382+02:00 error: name: my_name, exit_reason: "It crashed" + +2018-05-17T18:31:31.152864+02:00 error: name: my_name, exit_reason: "It crashed"
legacy_header=false, single_line=false @@ -236,7 +252,7 @@ exit_reason: "It crashed"

Example log entry:

-2018-05-16T11:55:50.448382+02:00 error: +2018-05-17T18:32:20.105422+02:00 error: name: my_name exit_reason: "It crashed" diff --git a/lib/kernel/doc/src/logger_std_h.xml b/lib/kernel/doc/src/logger_std_h.xml index bf23d874c8..a4f2848037 100644 --- a/lib/kernel/doc/src/logger_std_h.xml +++ b/lib/kernel/doc/src/logger_std_h.xml @@ -33,17 +33,17 @@ logger_std_h.xml logger_std_h - Default handler for the Logger application. + Default handler for Logger. -

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

This is the default handler for Logger. + Multiple instances of this handler can be added to + Logger, and each instance will print logs to standard_io, standard_error or to file. The default instance that starts - with kernel is named default - which is the name to be used + with Kernel is named default - which is the name to be used for reconfiguration.

The handler has an overload protection mechanism that will keep the handler - process and the kernel application alive during a high load of log + process and the Kernel application alive during a high load of log requests. How this feature works, and how to modify the configuration, is described in the User's Guide @@ -104,7 +104,7 @@ logger:add_handler(my_standard_h, logger_std_h, filesync_repeat_interval => 1000}}).

In order to configure the default handler (that starts initially with - the kernel application) to log to file instead of standard_io, + the Kernel application) to log to file instead of standard_io, change the Kernel default logger to use a file. Example:

erl -kernel logger '[{handler,default,logger_std_h, @@ -127,6 +127,11 @@ erl -kernel logger '[{handler,default,logger_std_h, +
+ See Also +

logger(3)

+

logger_disk_log_h(3)

+
diff --git a/lib/runtime_tools/doc/src/LTTng.xml b/lib/runtime_tools/doc/src/LTTng.xml index 93937b3fdc..4114542c74 100644 --- a/lib/runtime_tools/doc/src/LTTng.xml +++ b/lib/runtime_tools/doc/src/LTTng.xml @@ -111,7 +111,7 @@ $ make

process_register

pid : string :: Process ID. Ex. "<0.131.0>" - name : string :: Registered name. Ex. "error_logger" + name : string :: Registered name. Ex. "logger" type : string :: "register" | "unregister"

Example:

diff --git a/lib/sasl/doc/src/error_logging.xml b/lib/sasl/doc/src/error_logging.xml index 4b2c960bbb..44506ffdad 100644 --- a/lib/sasl/doc/src/error_logging.xml +++ b/lib/sasl/doc/src/error_logging.xml @@ -32,22 +32,51 @@ B error_logging.xml + +

The SASL error logging concept desribed in this section is + deprecated since OTP-21, when the + new logging + API was introduced.

+

The new default behaviour is that the SASL application no + longer affects which log events that are logged. + Supervisor + reports and crash + reports are logged via the default logger handler + which is setup by + Kernel. Progress + reports are by default not logged, but can be enabled + by setting the Kernel configuration + parameter + logger_log_progress to true.

+

The old SASL error logging behaviour can be re-enabled by setting the + Kernel configuration + parameter + logger_sasl_compatible to true.

+

The mechanism + for multi-file error report + logging as described in this section is also kept for + backwards compatibility. However, the new logging API also + introduces + logger_disk_log_h(3), which is a logger + handler that can print to multiple files + using disk_log(3).

+
+ +
+ SASL reports

The SASL application introduces three types of reports:

Supervisor report Progress report Crash report -

When the SASL application is started, it adds a handler that - formats and writes these reports, as specified in the configuration - parameters for SASL, that is, the environment variables - in the SASL application specification, which is found in the - .app file of SASL. For details, see the - sasl(6) application in the - Reference Manual and the app(4) - file in the Kernel Reference Manual.

+

When the SASL application is started, it adds a logger handler + that formats and writes these reports, as specified in + the configuration + parameters for SASL

+ Supervisor Report

A supervisor report is issued when a supervised child terminates unexpectedly. A supervisor report contains the following @@ -68,6 +97,7 @@

+ Progress Report

A progress report is issued when a supervisor starts or restarts a child. A progress report contains the following items:

@@ -82,6 +112,7 @@
+ Crash Report

Processes started with functions proc_lib:spawn or @@ -105,6 +136,7 @@ crash. The information gathered is the same as the information for Crasher, described in the previous item.

+
Example @@ -163,6 +195,7 @@
+ Multi-File Error Report Logging

Multi-file error report logging is used to store error messages received by error_logger. The error messages @@ -171,7 +204,8 @@ of files exist at the same time. The logging is very fast, as each error message is written as a binary term.

For more details, see the - sasl(6) + + sasl(6) application in the Reference Manual.

diff --git a/lib/sasl/doc/src/sasl_app.xml b/lib/sasl/doc/src/sasl_app.xml index 26b9bece2a..eb1e87d9a3 100644 --- a/lib/sasl/doc/src/sasl_app.xml +++ b/lib/sasl/doc/src/sasl_app.xml @@ -90,20 +90,22 @@
+ Deprecated Error Logger Event Handlers and Configuration

In OTP-21, a new API for logging was added to Erlang/OTP. The old error_logger event manager, and event handlers running on this manager, will still work, but they are not used by default.

The error logger event handlers sasl_report_tty_h - and sasl_report_file_h, were earliger used for printing + and sasl_report_file_h, were earlier used for printing the so called SASL reports, i.e. supervisor reports, crash reports, and progress - reports. These reports are now also printed by the standard + reports. These reports are now also printed by the default logger handler started by the Kernel application. Progress reports are by default stopped by a filter, but can easily be added by setting the Kernel configuration - parameter logger_log_progress=true.

+ parameter + logger_log_progress=true.

If the old error logger event handlers are still desired, they must be added by calling error_logger:add_report_handler/1,2.

@@ -218,6 +220,7 @@ See Also

alarm_handler(3), error_logger(3), + logger(3), log_mf_h(3), rb(3), release_handler(3), diff --git a/lib/stdlib/doc/src/gen_event.xml b/lib/stdlib/doc/src/gen_event.xml index 012737c390..51378a6b73 100644 --- a/lib/stdlib/doc/src/gen_event.xml +++ b/lib/stdlib/doc/src/gen_event.xml @@ -458,8 +458,7 @@ gen_event:stop -----> Module:terminate/2 with the expected reason. Any other reason than normal, shutdown, or {shutdown,Term} causes an error report to be issued using - - error_logger:format/2. + logger(3). The default Reason is normal.

Timeout is an integer greater than zero that specifies how many milliseconds to wait for the event manager to diff --git a/lib/stdlib/doc/src/gen_server.xml b/lib/stdlib/doc/src/gen_server.xml index da74e793e6..27edbc8de7 100644 --- a/lib/stdlib/doc/src/gen_server.xml +++ b/lib/stdlib/doc/src/gen_server.xml @@ -486,8 +486,7 @@ gen_server:abcast -----> Module:handle_cast/2 with the expected reason. Any other reason than normal, shutdown, or {shutdown,Term} causes an error report to be issued using - - error_logger:format/2. + logger(3). The default Reason is normal.

Timeout is an integer greater than zero that specifies how many milliseconds to wait for the server to @@ -861,8 +860,7 @@ gen_server:abcast -----> Module:handle_cast/2 shutdown, or {shutdown,Term}, the gen_server process is assumed to terminate because of an error and an error report is issued using - - error_logger:format/2.

+ logger(3).

diff --git a/lib/stdlib/doc/src/gen_statem.xml b/lib/stdlib/doc/src/gen_statem.xml index e918e83df7..a808d3af55 100644 --- a/lib/stdlib/doc/src/gen_statem.xml +++ b/lib/stdlib/doc/src/gen_statem.xml @@ -1778,7 +1778,7 @@ handle_event(_, _, State, Data) -> with the expected reason. Any other reason than normal, shutdown, or {shutdown,Term} causes an error report to be issued through - error_logger:format/2. + logger(3). The default Reason is normal.

@@ -2286,7 +2286,7 @@ init(Args) -> erlang:error(not_implemented, [Args]). shutdown, or {shutdown,Term}, the gen_statem is assumed to terminate because of an error and an error report is issued using - error_logger:format/2. + logger(3).

diff --git a/lib/stdlib/doc/src/proc_lib.xml b/lib/stdlib/doc/src/proc_lib.xml index cb152d1935..c4fdf972e4 100644 --- a/lib/stdlib/doc/src/proc_lib.xml +++ b/lib/stdlib/doc/src/proc_lib.xml @@ -59,18 +59,16 @@

When a process that is started using proc_lib terminates abnormally (that is, with another exit reason than normal, shutdown, or {shutdown,Term}), a crash report - is generated, which is written to terminal by the default SASL - event handler. That is, the crash report is normally only visible - if the SASL application is started; see - sasl(6) and section - SASL Error Logging - in the SASL User's Guide.

+ is generated, which is written to terminal by the default logger + handler setup by Kernel. For more information about how crash reports + were logged before OTP-21, see + SASL Error Logging in the SASL User's Guide.

Unlike in "plain Erlang", proc_lib processes will not generate error reports, which are written to the terminal by the - emulator and do not require SASL to be started. All exceptions are + emulator. All exceptions are converted to exits which are ignored by the default - error_logger handler.

+ logger handler.

The crash report contains the previously stored information, such as ancestors and initial function, the termination reason, and @@ -115,12 +113,22 @@ Format a crash report. -

This function can be used by a user-defined event handler to + +

This function is deprecated in the sense that + the error_logger is no longer the preferred + interface for logging in Erlang/OTP. A + new logging + API was added in OTP-21, but + legacy error_logger handlers may still be used. New + logger handlers do not need to used this function, since + the formatting callback (report_cb) is included as + metadata in the log event.

+ +

This function can be used by a user-defined legacy + error_logger event handler to format a crash report. The crash report is sent using - - error_logger:error_report(crash_report, - CrashReport). - That is, the event to be handled is of the format + + logger(3), and the event to be handled is of the format {error_report, GL, {Pid, crash_report, CrashReport}}, where GL is the group leader pid of process @@ -132,7 +140,19 @@ Format a crash report. -

This function can be used by a user-defined event handler to + +

This function is deprecated in the sense that + the error_logger is no longer the preferred + interface for logging in Erlang/OTP. A + new logging + API was added in OTP-21, but + legacy error_logger handlers may still be used. New + logger handlers do not need to used this function, since + the formatting callback (report_cb) is included as + metadata in the log event.

+ +

This function can be used by a user-defined legacy + error_logger event handler to format a crash report. When Depth is specified as a positive integer, it is used in the format string to limit the output as follows: io_lib:format("~P", @@ -395,6 +415,8 @@ init(Parent) -> See Also

error_logger(3)

+

+ logger(3)

-- cgit v1.2.3 From be959158a9ebe4b4ed8c336b969ac0c0e9399312 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Fri, 18 May 2018 11:54:32 +0200 Subject: Set legacy_header=true for kernel's default handler only --- lib/kernel/src/logger.erl | 10 +++++++++- lib/kernel/src/logger_h_common.erl | 2 +- lib/kernel/src/logger_internal.hrl | 3 +-- lib/kernel/src/logger_server.erl | 2 +- lib/kernel/test/logger_disk_log_h_SUITE.erl | 15 +++++++++++---- lib/kernel/test/logger_env_var_SUITE.erl | 4 ++-- lib/kernel/test/logger_simple_SUITE.erl | 6 ++++-- lib/kernel/test/logger_std_h_SUITE.erl | 17 ++++++++++++----- 8 files changed, 41 insertions(+), 18 deletions(-) (limited to 'lib') diff --git a/lib/kernel/src/logger.erl b/lib/kernel/src/logger.erl index 281521ae6e..51743822af 100644 --- a/lib/kernel/src/logger.erl +++ b/lib/kernel/src/logger.erl @@ -677,7 +677,8 @@ init_default_config(Type) when Type==standard_io; Type==standard_error; element(1,Type)==file -> Env = get_logger_env(), - DefaultConfig = #{logger_std_h=>#{type=>Type}}, + DefaultFormatter = #{formatter=>{?DEFAULT_FORMATTER,?DEFAULT_FORMAT_CONFIG}}, + DefaultConfig = DefaultFormatter#{logger_std_h=>#{type=>Type}}, NewLoggerEnv = case lists:keyfind(default, 2, Env) of {handler, default, Module, Config} -> @@ -687,6 +688,13 @@ init_default_config(Type) when Type==standard_io; %% if not configured by user AND the default %% handler is still the logger_std_h. {handler, default, Module, maps:merge(DefaultConfig,Config)}; + ({handler, default, logger_disk_log_h, _}) -> + %% Add default formatter. The point of this + %% is to get the expected formatter config + %% for the default handler, since this + %% differs from the default values that + %% logger_formatter itself adds. + {handler, default, logger_disk_log_h, maps:merge(DefaultFormatter,Config)}; (Other) -> Other end, Env); diff --git a/lib/kernel/src/logger_h_common.erl b/lib/kernel/src/logger_h_common.erl index 901c4c0dad..70531c0e34 100644 --- a/lib/kernel/src/logger_h_common.erl +++ b/lib/kernel/src/logger_h_common.erl @@ -72,7 +72,7 @@ try_format(Log,Formatter,FormatterConfig) -> {log,Log}, {reason, {C,R,logger:filter_stacktrace(?MODULE,S)}}]), - case {?DEFAULT_FORMATTER,?DEFAULT_FORMAT_CONFIG} of + case {?DEFAULT_FORMATTER,#{}} of {Formatter,FormatterConfig} -> "DEFAULT FORMATTER CRASHED"; {DefaultFormatter,DefaultConfig} -> diff --git a/lib/kernel/src/logger_internal.hrl b/lib/kernel/src/logger_internal.hrl index f9377259f3..97ef4abfa4 100644 --- a/lib/kernel/src/logger_internal.hrl +++ b/lib/kernel/src/logger_internal.hrl @@ -31,8 +31,7 @@ {no_domain,{fun logger_filters:domain/2,{log,no_domain,[]}}}]). -define(DEFAULT_FORMATTER,logger_formatter). -define(DEFAULT_FORMAT_CONFIG,#{legacy_header=>true, - single_line=>false, - template=>?DEFAULT_FORMAT_TEMPLATE_HEADER}). + single_line=>false}). -define(DEFAULT_FORMAT_TEMPLATE_HEADER, [{logger_formatter,header},"\n",msg,"\n"]). -define(DEFAULT_FORMAT_TEMPLATE_SINGLE, diff --git a/lib/kernel/src/logger_server.erl b/lib/kernel/src/logger_server.erl index 275b9c476f..67befef156 100644 --- a/lib/kernel/src/logger_server.erl +++ b/lib/kernel/src/logger_server.erl @@ -328,7 +328,7 @@ default_config(_) -> #{level=>info, filters=>[], filter_default=>log, - formatter=>{?DEFAULT_FORMATTER,?DEFAULT_FORMAT_CONFIG}}. + formatter=>{?DEFAULT_FORMATTER,#{}}}. sanity_check(Owner,Key,Value) -> sanity_check_1(Owner,[{Key,Value}]). diff --git a/lib/kernel/test/logger_disk_log_h_SUITE.erl b/lib/kernel/test/logger_disk_log_h_SUITE.erl index 3aa1c3557b..7a1736c814 100644 --- a/lib/kernel/test/logger_disk_log_h_SUITE.erl +++ b/lib/kernel/test/logger_disk_log_h_SUITE.erl @@ -336,24 +336,24 @@ formatter_fail(Config) -> {ok,{_,#{formatter:={logger_formatter,_}}}} = logger:get_handler_config(Name), logger:info(M1=?msg,?domain), - Got1 = try_match_file(?log_no(LogFile,1),"=INFO REPORT====.*\n"++M1,5000), + Got1 = try_match_file(?log_no(LogFile,1),"[0-9\\+\\-T:\\.]* info: "++M1,5000), ok = logger:set_handler_config(Name,formatter,{nonexistingmodule,#{}}), logger:info(M2=?msg,?domain), Got2 = try_match_file(?log_no(LogFile,1), - Got1++"=INFO REPORT====.*\nFORMATTER CRASH: .*"++M2, + escape(Got1)++"[0-9\\+\\-T:\\.]* info: FORMATTER CRASH: .*"++M2, 5000), ok = logger:set_handler_config(Name,formatter,{?MODULE,crash}), logger:info(M3=?msg,?domain), Got3 = try_match_file(?log_no(LogFile,1), - Got2++"=INFO REPORT====.*\nFORMATTER CRASH: .*"++M3, + escape(Got2)++"[0-9\\+\\-T:\\.]* info: FORMATTER CRASH: .*"++M3, 5000), ok = logger:set_handler_config(Name,formatter,{?MODULE,bad_return}), logger:info(?msg,?domain), try_match_file(?log_no(LogFile,1), - Got3++"FORMATTER ERROR: bad_return_value", + escape(Got3)++"FORMATTER ERROR: bad_return_value", 5000), %% Check that handler is still alive and was never dead @@ -1491,3 +1491,10 @@ check_tracer(T) -> dbg:stop_clear(), ct:fail({timeout,tracer}) end. + +escape([$+|Rest]) -> + [$\\,$+|escape(Rest)]; +escape([H|T]) -> + [H|escape(T)]; +escape([]) -> + []. diff --git a/lib/kernel/test/logger_env_var_SUITE.erl b/lib/kernel/test/logger_env_var_SUITE.erl index 764f443634..32612d616e 100644 --- a/lib/kernel/test/logger_env_var_SUITE.erl +++ b/lib/kernel/test/logger_env_var_SUITE.erl @@ -542,8 +542,8 @@ logger_many_handlers(Config, Env, LogErr, LogInfo, NumProgress) -> ok = rpc:call(Node,logger_std_h,filesync,[info]), {ok, Bin} = file:read_file(LogInfo), ct:log("Log content:~n~s",[Bin]), - match(Bin,<<"PROGRESS REPORT">>,NumProgress,info,info), - match(Bin,<<"ALERT REPORT">>,0,alert,info), + match(Bin,<<"info:">>,NumProgress+1,info,info), + match(Bin,<<"alert:">>,0,alert,info), ok. diff --git a/lib/kernel/test/logger_simple_SUITE.erl b/lib/kernel/test/logger_simple_SUITE.erl index 0d505b14f5..d7f9fa21cf 100644 --- a/lib/kernel/test/logger_simple_SUITE.erl +++ b/lib/kernel/test/logger_simple_SUITE.erl @@ -138,7 +138,8 @@ replace_file(Config) -> ok = rpc:call(Node, logger, add_handlers, [[{handler, default, logger_std_h, - #{ logger_std_h => #{ type => {file, File} }}}]]), + #{ logger_std_h => #{ type => {file, File} }, + formatter => {?DEFAULT_FORMATTER,?DEFAULT_FORMAT_CONFIG}}}]]), {ok,Bin} = sync_and_read(Node, file, File), Lines = [unicode:characters_to_list(L) || @@ -181,7 +182,8 @@ replace_disk_log(Config) -> ok = rpc:call(Node, logger, add_handlers, [[{handler, default, logger_disk_log_h, - #{ disk_log_opts => #{ file => File }}}]]), + #{ disk_log_opts => #{ file => File }, + formatter => {?DEFAULT_FORMATTER,?DEFAULT_FORMAT_CONFIG}}}]]), {ok,Bin} = sync_and_read(Node, disk_log, File), Lines = [unicode:characters_to_list(L) || L <- binary:split(Bin,<<"\n">>,[global,trim])], diff --git a/lib/kernel/test/logger_std_h_SUITE.erl b/lib/kernel/test/logger_std_h_SUITE.erl index fc59d393e0..5764abd063 100644 --- a/lib/kernel/test/logger_std_h_SUITE.erl +++ b/lib/kernel/test/logger_std_h_SUITE.erl @@ -250,24 +250,24 @@ formatter_fail(Config) -> {ok,{_,#{formatter:={logger_formatter,_}}}} = logger:get_handler_config(?MODULE), logger:info(M1=?msg,?domain), - Got1 = try_match_file(Log,"=INFO REPORT====.*\n"++M1,5000), + Got1 = try_match_file(Log,"[0-9\\+\\-T:\\.]* info: "++M1,5000), ok = logger:set_handler_config(?MODULE,formatter,{nonexistingmodule,#{}}), logger:info(M2=?msg,?domain), Got2 = try_match_file(Log, - Got1++"=INFO REPORT====.*\nFORMATTER CRASH: .*"++M2, + escape(Got1)++"[0-9\\+\\-T:\\.]* info: FORMATTER CRASH: .*"++M2, 5000), ok = logger:set_handler_config(?MODULE,formatter,{?MODULE,crash}), logger:info(M3=?msg,?domain), Got3 = try_match_file(Log, - Got2++"=INFO REPORT====.*\nFORMATTER CRASH: .*"++M3, + escape(Got2)++"[0-9\\+\\-T:\\.]* info: FORMATTER CRASH: .*"++M3, 5000), ok = logger:set_handler_config(?MODULE,formatter,{?MODULE,bad_return}), logger:info(?msg,?domain), try_match_file(Log, - Got3++"FORMATTER ERROR: bad_return_value", + escape(Got3)++"FORMATTER ERROR: bad_return_value", 5000), %% Check that handler is still alive and was never dead @@ -1020,7 +1020,7 @@ mem_kill_new(Config) -> killed -> ct:pal("Slow shutdown, handler process was killed!", []) end, - timer:sleep(RestartAfter + 2000), + timer:sleep(RestartAfter * 3), true = is_pid(whereis(?MODULE)), ok after @@ -1518,3 +1518,10 @@ check_tracer(T,TimeoutFun) -> dbg:stop_clear(), TimeoutFun() end. + +escape([$+|Rest]) -> + [$\\,$+|escape(Rest)]; +escape([H|T]) -> + [H|escape(T)]; +escape([]) -> + []. -- cgit v1.2.3 From cfbe1afe6ba1f1083c8aa41c7aeb422f253f5d23 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Fri, 18 May 2018 13:27:56 +0200 Subject: Add logger:update_formatter_config/2,3 --- lib/kernel/doc/src/logger.xml | 25 ++++++++++++ lib/kernel/doc/src/logger_chapter.xml | 6 +-- lib/kernel/src/logger.erl | 18 ++++++++- lib/kernel/src/logger_server.erl | 26 ++++++++++++- lib/kernel/test/logger_formatter_SUITE.erl | 61 +++++++++++++++++++++++++++++- 5 files changed, 130 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/kernel/doc/src/logger.xml b/lib/kernel/doc/src/logger.xml index f7e740e90d..be733685cc 100644 --- a/lib/kernel/doc/src/logger.xml +++ b/lib/kernel/doc/src/logger.xml @@ -773,6 +773,31 @@ logger:set_handler_config(HandlerId,maps:merge(Old,Config)). + + + Update the formatter configuration for the specified handler. + +

Update the formatter configuration for the specified handler.

+

The new configuration is merged with the existing formatter + configuration.

+

To overwrite the existing configuration without any merge, + use + set_handler_config(HandlerId,formatter, + {FormatterModule,FormatterConfig}).

+
+
+ + + + Update the formatter configuration for the specified handler. + +

Update the formatter configuration for the specified handler.

+

This is equivalent + to
+ update_formatter_config(HandlerId,#{Key=>Value})

+
+
+ Compare the severity of two log levels. diff --git a/lib/kernel/doc/src/logger_chapter.xml b/lib/kernel/doc/src/logger_chapter.xml index 21b460e72a..522d0ce29d 100644 --- a/lib/kernel/doc/src/logger_chapter.xml +++ b/lib/kernel/doc/src/logger_chapter.xml @@ -157,7 +157,7 @@

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

- format(Log,Extra) -> unicode:chardata() + 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 @@ -413,12 +413,12 @@ return ignore.

Default is log.

- formatter = {Module::module(),Extra::term()} + formatter = {FModule::module(),FConfig::map()}

See Formatter for more information.

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

HandlerConfig, term() = term() diff --git a/lib/kernel/src/logger.erl b/lib/kernel/src/logger.erl index 51743822af..d60be180bc 100644 --- a/lib/kernel/src/logger.erl +++ b/lib/kernel/src/logger.erl @@ -41,6 +41,7 @@ set_logger_config/1, set_logger_config/2, set_handler_config/2, set_handler_config/3, update_logger_config/1, update_handler_config/2, + update_formatter_config/2, update_formatter_config/3, get_logger_config/0, get_handler_config/1, add_handlers/1]). @@ -92,7 +93,7 @@ -type config() :: #{level => level(), filter_default => log | stop, filters => [{filter_id(),filter()}], - formatter => {module(),term()}, + formatter => {module(),map()}, term() => term()}. -type timestamp() :: integer(). @@ -386,6 +387,21 @@ get_logger_config() -> get_handler_config(HandlerId) -> logger_config:get(?LOGGER_TABLE,HandlerId). +-spec update_formatter_config(HandlerId,FormatterConfig) -> + ok | {error,term()} when + HandlerId :: config(), + FormatterConfig :: map(). +update_formatter_config(HandlerId,FormatterConfig) -> + logger_server:update_formatter_config(HandlerId,FormatterConfig). + +-spec update_formatter_config(HandlerId,Key,Value) -> + ok | {error,term()} when + HandlerId :: config(), + Key :: atom(), + Value :: term(). +update_formatter_config(HandlerId,Key,Value) -> + logger_server:update_formatter_config(HandlerId,#{Key=>Value}). + -spec set_module_level(Module,Level) -> ok | {error,term()} when Module :: module(), Level :: level(). diff --git a/lib/kernel/src/logger_server.erl b/lib/kernel/src/logger_server.erl index 67befef156..18a784c8c2 100644 --- a/lib/kernel/src/logger_server.erl +++ b/lib/kernel/src/logger_server.erl @@ -27,7 +27,8 @@ add_filter/2, remove_filter/2, set_module_level/2, reset_module_level/1, cache_module_level/1, - set_config/2, set_config/3, update_config/2]). + set_config/2, set_config/3, update_config/2, + update_formatter_config/2]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, @@ -111,6 +112,13 @@ update_config(Owner, Config) -> Error end. +update_formatter_config(HandlerId, FormatterConfig) + when is_map(FormatterConfig) -> + call({update_formatter_config,HandlerId,FormatterConfig}); +update_formatter_config(_HandlerId, FormatterConfig) -> + {error,{invalid_formatter_config,FormatterConfig}}. + + %%%=================================================================== %%% gen_server callbacks %%%=================================================================== @@ -216,6 +224,22 @@ handle_call({set_config,HandlerId,Config}, From, #state{tid=Tid}=State) -> _ -> {reply,{error,{not_found,HandlerId}},State} end; +handle_call({update_formatter_config,HandlerId,NewFConfig},_From, + #state{tid=Tid}=State) -> + Reply = + case logger_config:get(Tid,HandlerId) of + {ok,{_Mod,#{formatter:={FMod,OldFConfig}}=Config}} -> + try + FConfig = maps:merge(OldFConfig,NewFConfig), + check_formatter({FMod,FConfig}), + do_set_config(Tid,HandlerId, + Config#{formatter=>{FMod,FConfig}}) + catch throw:Reason -> {error,Reason} + end; + _ -> + {error,{not_found,HandlerId}} + end, + {reply,Reply,State}; handle_call({set_module_level,Module,Level}, _From, #state{tid=Tid}=State) -> Reply = logger_config:set_module_level(Tid,Module,Level), {reply,Reply,State}; diff --git a/lib/kernel/test/logger_formatter_SUITE.erl b/lib/kernel/test/logger_formatter_SUITE.erl index c171165944..934fe4deef 100644 --- a/lib/kernel/test/logger_formatter_SUITE.erl +++ b/lib/kernel/test/logger_formatter_SUITE.erl @@ -68,7 +68,8 @@ all() -> level_or_msg_in_meta, faulty_log, faulty_config, - faulty_msg]. + faulty_msg, + update_config]. default(_Config) -> String1 = format(info,{"~p",[term]},#{},#{}), @@ -532,6 +533,54 @@ faulty_msg(_Config) -> #{})), ok. +%% Test that formatter config can be changed, and that the default +%% template is updated accordingly +update_config(_Config) -> + logger:add_handler_filter(default,silence,{fun(_,_) -> stop end,ok}), + ok = logger:add_handler(?MODULE,?MODULE,#{}), + D = lists:seq(1,1000), + logger:info("~p~n",[D]), + {Lines1,C1} = check_log(), + [ct:log(L) || L <- Lines1], + ct:log("~p",[C1]), + [Line1] = Lines1, + [_Time,"info: "++D1] = string:split(Line1," "), + true = length(D1)>3000, + true = #{}==C1, + + ok = logger:update_formatter_config(?MODULE,single_line,false), + logger:info("~p~n",[D]), + {Lines2,C2} = check_log(), + [ct:log(L) || L <- Lines2], + ct:log("~p",[C2]), + true = length(Lines2)>50, + true = #{single_line=>false}==C2, + + ok = logger:update_formatter_config(?MODULE,#{legacy_header=>true}), + logger:info("~p~n",[D]), + {Lines3,C3} = check_log(), + [ct:log(L) || L <- Lines3], + ct:log("~p",[C3]), + ["=INFO REPORT==== "++_|D3] = Lines3, + true = length(D3)>50, + true = #{legacy_header=>true,single_line=>false}==C3, + + ok = logger:update_formatter_config(?MODULE,single_line,true), + logger:info("~p~n",[D]), + {Lines4,C4} = check_log(), + [ct:log(L) || L <- Lines4], + ct:log("~p",[C4]), + ["=INFO REPORT==== "++_,D4] = Lines4, + true = length(D4)>3000, + true = #{legacy_header=>true,single_line=>true}==C4, + + ok. + +update_config(cleanup,_Config) -> + _ = logger:remove_handler(?MODULE), + _ = logger:remove_handler_filter(default,silence), + ok. + %%%----------------------------------------------------------------- %%% Internal format(Level,Msg,Meta,Config) -> @@ -575,3 +624,13 @@ add_time(#{time:=_}=Meta) -> Meta; add_time(Meta) -> Meta#{time=>timestamp()}. + +%%%----------------------------------------------------------------- +%%% handler callback +log(Log,#{formatter:={M,C}}) -> + put(log,{M:format(Log,C),C}), + ok. + +check_log() -> + {S,C} = erase(log), + {string:lexemes(S,"\n"),C}. -- cgit v1.2.3 From 4a055a655e1f82639b261689e56cbf2f1dc2d5c3 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Fri, 18 May 2018 14:49:42 +0200 Subject: Allow chars_limit to limit strings Earlier, only reports and {Format,Args} was limited by chars_limit, and max_size was needed to limit the size of a string. --- lib/kernel/src/logger_formatter.erl | 6 +----- lib/kernel/test/logger_formatter_SUITE.erl | 12 ++++++++++-- 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/kernel/src/logger_formatter.erl b/lib/kernel/src/logger_formatter.erl index a19e7bbc73..5882c70ddf 100644 --- a/lib/kernel/src/logger_formatter.erl +++ b/lib/kernel/src/logger_formatter.erl @@ -85,8 +85,6 @@ format(#{level:=Level,msg:=Msg0,meta:=Meta},Config0) do_format(Level,Msg,Data,[level|Format],Config) -> [to_string(level,Level,Config)|do_format(Level,Msg,Data,Format,Config)]; -do_format(Level,Msg,Data,[msg|Format],Config) -> - [Msg|do_format(Level,Msg,Data,Format,Config)]; do_format(Level,Msg,Data,[Key|Format],Config) when is_atom(Key); is_tuple(Key) -> Value = value(Key,Data), [to_string(Key,Value,Config)|do_format(Level,Msg,Data,Format,Config)]; @@ -130,9 +128,7 @@ to_string(X) -> io_lib:format("~tp",[X]). format_msg({string,Chardata},Meta,Config) -> - try unicode:characters_to_list(Chardata) - catch _:_ -> format_msg({"INVALID STRING: ~tp",[Chardata]},Meta,Config) - end; + format_msg({"~ts",[Chardata]},Meta,Config); format_msg({report,_}=Msg,Meta,#{report_cb:=Fun}=Config) when is_function(Fun,1) -> format_msg(Msg,Meta#{report_cb=>Fun},maps:remove(report_cb,Config)); format_msg({report,Report},#{report_cb:=Fun}=Meta,Config) when is_function(Fun,1) -> diff --git a/lib/kernel/test/logger_formatter_SUITE.erl b/lib/kernel/test/logger_formatter_SUITE.erl index 934fe4deef..eaa6c0aca5 100644 --- a/lib/kernel/test/logger_formatter_SUITE.erl +++ b/lib/kernel/test/logger_formatter_SUITE.erl @@ -269,8 +269,8 @@ format_msg(_Config) -> String8 = format(info,{string,['not',printable,list]}, #{report_cb=>fun(_)-> {"formatted",[]} end}, #{template=>Template}), - ct:log(String8), - "INVALID STRING: ['not',printable,list]" = String8, + ct:log("~ts",[String8]), % avoiding ct_log crash + "FORMAT ERROR: \"~ts\" - [['not',printable,list]]" = String8, String9 = format(info,{string,"string"},#{},#{template=>Template}), ct:log(String9), @@ -406,6 +406,14 @@ chars_limit(_Config) -> L5 = MS5, true = lists:prefix(lists:sublist(String5,L5-4),String4), + %% Test that chars_limit limits string also + Str = "123456789012345678901234567890123456789012345678901234567890123456789", + CL6 = 80, + String6 = format(info,{string,Str},Meta,FC#{chars_limit=>CL6}), + L6 = string:length(String6), + ct:log("String6: ~p~nLength6: ~p~n",[String6,L6]), + L6 = CL6, + ok. format_mfa(_Config) -> -- cgit v1.2.3 From 6342a95bdaa8681bf24f2dc8fba261d21b75c9e4 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Fri, 18 May 2018 14:26:24 +0200 Subject: Rename reset_module_level to unset_module_level --- lib/kernel/doc/src/logger.xml | 2 +- lib/kernel/src/logger.erl | 8 ++++---- lib/kernel/src/logger_config.erl | 4 ++-- lib/kernel/src/logger_server.erl | 12 ++++++------ lib/kernel/test/logger_SUITE.erl | 14 +++++++------- 5 files changed, 20 insertions(+), 20 deletions(-) (limited to 'lib') diff --git a/lib/kernel/doc/src/logger.xml b/lib/kernel/doc/src/logger.xml index be733685cc..13d3e182d4 100644 --- a/lib/kernel/doc/src/logger.xml +++ b/lib/kernel/doc/src/logger.xml @@ -613,7 +613,7 @@ Current logger configuration:
- + Remove a module specific log setting.

Remove a module specific log setting. After this, the diff --git a/lib/kernel/src/logger.erl b/lib/kernel/src/logger.erl index d60be180bc..2a0e2e5f50 100644 --- a/lib/kernel/src/logger.erl +++ b/lib/kernel/src/logger.erl @@ -37,7 +37,7 @@ -export([add_handler/3, remove_handler/1, add_logger_filter/2, add_handler_filter/3, remove_logger_filter/1, remove_handler_filter/2, - set_module_level/2, reset_module_level/1, + set_module_level/2, unset_module_level/1, set_logger_config/1, set_logger_config/2, set_handler_config/2, set_handler_config/3, update_logger_config/1, update_handler_config/2, @@ -408,10 +408,10 @@ update_formatter_config(HandlerId,Key,Value) -> set_module_level(Module,Level) -> logger_server:set_module_level(Module,Level). --spec reset_module_level(Module) -> ok | {error,term()} when +-spec unset_module_level(Module) -> ok | {error,term()} when Module :: module(). -reset_module_level(Module) -> - logger_server:reset_module_level(Module). +unset_module_level(Module) -> + logger_server:unset_module_level(Module). %%%----------------------------------------------------------------- %%% Misc diff --git a/lib/kernel/src/logger_config.erl b/lib/kernel/src/logger_config.erl index 40dc1b1e1b..1d35c2e068 100644 --- a/lib/kernel/src/logger_config.erl +++ b/lib/kernel/src/logger_config.erl @@ -24,7 +24,7 @@ allow/2,allow/3, get/2, get/3, get/1, create/3, create/4, set/3, - set_module_level/3,reset_module_level/2, + set_module_level/3,unset_module_level/2, cache_module_level/2, level_to_int/1]). @@ -109,7 +109,7 @@ set_module_level(Tid,Module,Level) -> ets:insert(Tid,{Module,level_to_int(Level)}), ok. -reset_module_level(Tid,Module) -> +unset_module_level(Tid,Module) -> ets:delete(Tid,Module), % should possibley overwrite instead of delete? ok. diff --git a/lib/kernel/src/logger_server.erl b/lib/kernel/src/logger_server.erl index 18a784c8c2..16f61abdd6 100644 --- a/lib/kernel/src/logger_server.erl +++ b/lib/kernel/src/logger_server.erl @@ -25,7 +25,7 @@ -export([start_link/0, add_handler/3, remove_handler/1, add_filter/2, remove_filter/2, - set_module_level/2, reset_module_level/1, + set_module_level/2, unset_module_level/1, cache_module_level/1, set_config/2, set_config/3, update_config/2, update_formatter_config/2]). @@ -83,9 +83,9 @@ set_module_level(Module,Level) when is_atom(Module) -> set_module_level(Module,_) -> {error,{not_a_module,Module}}. -reset_module_level(Module) when is_atom(Module) -> - call({reset_module_level,Module}); -reset_module_level(Module) -> +unset_module_level(Module) when is_atom(Module) -> + call({unset_module_level,Module}); +unset_module_level(Module) -> {error,{not_a_module,Module}}. cache_module_level(Module) -> @@ -243,8 +243,8 @@ handle_call({update_formatter_config,HandlerId,NewFConfig},_From, handle_call({set_module_level,Module,Level}, _From, #state{tid=Tid}=State) -> Reply = logger_config:set_module_level(Tid,Module,Level), {reply,Reply,State}; -handle_call({reset_module_level,Module}, _From, #state{tid=Tid}=State) -> - Reply = logger_config:reset_module_level(Tid,Module), +handle_call({unset_module_level,Module}, _From, #state{tid=Tid}=State) -> + Reply = logger_config:unset_module_level(Tid,Module), {reply,Reply,State}. handle_cast({async_req_reply,_Ref,_Reply} = Reply,State) -> diff --git a/lib/kernel/test/logger_SUITE.erl b/lib/kernel/test/logger_SUITE.erl index 1d3410e356..66eee8219a 100644 --- a/lib/kernel/test/logger_SUITE.erl +++ b/lib/kernel/test/logger_SUITE.erl @@ -318,7 +318,7 @@ macros(_Config) -> macros(cleanup,_Config) -> logger:remove_handler(h1), - logger:reset_module_level(?MODULE), + logger:unset_module_level(?MODULE), ok. set_level(_Config) -> @@ -350,29 +350,29 @@ set_level_module(_Config) -> logger:info(M2=?map_rep,?MY_LOC(0)), ok = check_logged(info,M2,?MY_LOC(1)), - {error,{not_a_module,{bad}}} = logger:reset_module_level({bad}), - ok = logger:reset_module_level(?MODULE), + {error,{not_a_module,{bad}}} = logger:unset_module_level({bad}), + ok = logger:unset_module_level(?MODULE), ok. set_level_module(cleanup,_Config) -> logger:remove_handler(h1), - logger:reset_module_level(?MODULE), + logger:unset_module_level(?MODULE), ok. cache_level_module(_Config) -> - ok = logger:reset_module_level(?MODULE), + ok = logger:unset_module_level(?MODULE), [] = ets:lookup(logger,?MODULE), %dirty - add API in logger_config? ?LOG_INFO(?map_rep), %% Caching is done asynchronously, so wait a bit for the update timer:sleep(100), [_] = ets:lookup(logger,?MODULE), %dirty - add API in logger_config? - ok = logger:reset_module_level(?MODULE), + ok = logger:unset_module_level(?MODULE), [] = ets:lookup(logger,?MODULE), %dirty - add API in logger_config? ok. cache_level_module(cleanup,_Config) -> - logger:reset_module_level(?MODULE), + logger:unset_module_level(?MODULE), ok. format_report(_Config) -> -- cgit v1.2.3 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(-) (limited to 'lib') 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 From d35c100a10239edc669b465a2176000ffcc1300f Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Mon, 21 May 2018 16:47:46 +0200 Subject: Change Compare parameter to logger_filters:domain/2 This configuration option has been removed. logger_formatter will read the utc_log configuration parameter and format the timestamp accordingly. --- lib/kernel/doc/src/logger.xml | 4 +- lib/kernel/doc/src/logger_chapter.xml | 2 +- lib/kernel/doc/src/logger_filters.xml | 145 ++++++++++++++++++++----------- lib/kernel/src/logger_filters.erl | 24 ++--- lib/kernel/src/logger_internal.hrl | 4 +- lib/kernel/test/logger_env_var_SUITE.erl | 28 +++--- lib/kernel/test/logger_filters_SUITE.erl | 134 ++++++++++++++-------------- lib/kernel/test/logger_legacy_SUITE.erl | 4 +- lib/sasl/src/sasl.erl | 13 +-- 9 files changed, 195 insertions(+), 163 deletions(-) (limited to 'lib') diff --git a/lib/kernel/doc/src/logger.xml b/lib/kernel/doc/src/logger.xml index e2f3dd6e83..6e50473fa8 100644 --- a/lib/kernel/doc/src/logger.xml +++ b/lib/kernel/doc/src/logger.xml @@ -421,10 +421,10 @@ Current logger configuration: Config: stop Id: domain Fun: fun logger_filters:domain/2 - Config: {log,prefix_of,[beam,erlang,otp,sasl]} + Config: {log,super,[beam,erlang,otp,sasl]} Id: no_domain Fun: fun logger_filters:domain/2 - Config: {log,no_domain,[]} + Config: {log,undefined,[]} Handler Config: logger_std_h: #{type => standard_io} Level set per module: diff --git a/lib/kernel/doc/src/logger_chapter.xml b/lib/kernel/doc/src/logger_chapter.xml index fd86e9e366..34c65be47a 100644 --- a/lib/kernel/doc/src/logger_chapter.xml +++ b/lib/kernel/doc/src/logger_chapter.xml @@ -594,7 +594,7 @@ except the former so called "SASL reports", look the same as before.

- SASL Reports + SASL Reports

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

diff --git a/lib/kernel/doc/src/logger_filters.xml b/lib/kernel/doc/src/logger_filters.xml index 1bbae8be21..f92181ea3f 100644 --- a/lib/kernel/doc/src/logger_filters.xml +++ b/lib/kernel/doc/src/logger_filters.xml @@ -52,61 +52,100 @@ - Filter log events based on the domain field in metadata. + 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 = differs -

The filter matches if Domain differs - from MatchDomain, or if there is no domain field - in metadata.

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

- - +

This filter provides a way of filtering log events based on a + domain field in Metadata. 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.

+ +

A domain field must be a list of atoms, creating smaller + and more specialized domains as the list grows longer. The + biggest domain is [], which comprices all + possible domains.

+ +

For example, consider the following domains:

+
+D1 = [beam,erlang,otp]
+D2 = [beam,erlang,otp,sasl]
+ +

D1 is the biggest of the two, and is said to be a + super-domain of D2. D2 is a + sub-domain D1. Both D1 and D2 are + sub-domains of []

+ +

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 SASL + report.

+ +

The Extra parameter to + the domain/2 function 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 = sub + +

The filter matches if Domain is equal to or + a sub-domain of MatchDomain, that is, + if MatchDomain is a prefix of Domain.

+
+ Compare = super + +

The filter matches if Domain is equal to or a + super-domain of MatchDomain, that is, + if Domain is a prefix of MatchDomain.

+
+ Compare = equal + +

The filter matches if Domain is equal + to MatchDomain.

+
+ Compare = not_equal + +

The filter matches if Domain is not equal + to MatchDomain, or if there is no domain field in + metadata.

+
+ Compare = undefined +

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

+
+
+ +

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, decide if the + event is allowed or not.

+ +

Log events that do not contain any domain field, match only + when Compare = undefined + or Compare = not_equal.

+ +

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]}}. +Filter = {fun logger_filters:domain/2,{stop,sub,[beam,erlang,otp,sasl]}}. logger:add_handler_filter(h1,no_sasl,Filter). ok
diff --git a/lib/kernel/src/logger_filters.erl b/lib/kernel/src/logger_filters.erl index 592ff28cc2..322aa0265d 100644 --- a/lib/kernel/src/logger_filters.erl +++ b/lib/kernel/src/logger_filters.erl @@ -31,15 +31,15 @@ Log :: logger:log(), Extra :: {Action,Compare,MatchDomain}, Action :: log | stop, - Compare :: prefix_of | starts_with | equals | no_domain, + Compare :: super | sub | equal | not_equal | undefined, MatchDomain :: list(atom()). domain(#{meta:=Meta}=Log,{Action,Compare,MatchDomain}) when ?IS_ACTION(Action) andalso - (Compare==prefix_of orelse - Compare==starts_with orelse - Compare==equals orelse - Compare==differs orelse - Compare==no_domain) andalso + (Compare==super orelse + Compare==sub orelse + Compare==equal orelse + Compare==not_equal orelse + Compare==undefined) andalso is_list(MatchDomain) -> filter_domain(Compare,Meta,MatchDomain,on_match(Action,Log)); domain(Log,Extra) -> @@ -82,18 +82,18 @@ remote_gl(Log,Action) -> %%%----------------------------------------------------------------- %%% Internal -filter_domain(prefix_of,#{domain:=Domain},MatchDomain,OnMatch) -> +filter_domain(super,#{domain:=Domain},MatchDomain,OnMatch) -> is_prefix(Domain,MatchDomain,OnMatch); -filter_domain(starts_with,#{domain:=Domain},MatchDomain,OnMatch) -> +filter_domain(sub,#{domain:=Domain},MatchDomain,OnMatch) -> is_prefix(MatchDomain,Domain,OnMatch); -filter_domain(equals,#{domain:=Domain},Domain,OnMatch) -> +filter_domain(equal,#{domain:=Domain},Domain,OnMatch) -> OnMatch; -filter_domain(differs,#{domain:=Domain},MatchDomain,OnMatch) +filter_domain(not_equal,#{domain:=Domain},MatchDomain,OnMatch) when Domain=/=MatchDomain -> OnMatch; -filter_domain(Action,Meta,_,OnMatch) -> +filter_domain(Compare,Meta,_,OnMatch) -> case maps:is_key(domain,Meta) of - false when Action==no_domain; Action==differs -> OnMatch; + false when Compare==undefined; Compare==not_equal -> OnMatch; _ -> ignore end. diff --git a/lib/kernel/src/logger_internal.hrl b/lib/kernel/src/logger_internal.hrl index 97ef4abfa4..fedd6db370 100644 --- a/lib/kernel/src/logger_internal.hrl +++ b/lib/kernel/src/logger_internal.hrl @@ -27,8 +27,8 @@ ?DEFAULT_HANDLER_FILTERS([beam,erlang,otp])). -define(DEFAULT_HANDLER_FILTERS(Domain), [{remote_gl,{fun logger_filters:remote_gl/2,stop}}, - {domain,{fun logger_filters:domain/2,{log,prefix_of,Domain}}}, - {no_domain,{fun logger_filters:domain/2,{log,no_domain,[]}}}]). + {domain,{fun logger_filters:domain/2,{log,super,Domain}}}, + {no_domain,{fun logger_filters:domain/2,{log,undefined,[]}}}]). -define(DEFAULT_FORMATTER,logger_formatter). -define(DEFAULT_FORMAT_CONFIG,#{legacy_header=>true, single_line=>false}). diff --git a/lib/kernel/test/logger_env_var_SUITE.erl b/lib/kernel/test/logger_env_var_SUITE.erl index 32612d616e..081d4f0a80 100644 --- a/lib/kernel/test/logger_env_var_SUITE.erl +++ b/lib/kernel/test/logger_env_var_SUITE.erl @@ -82,7 +82,7 @@ default(Config) -> {?STANDARD_HANDLER,logger_std_h,StdC} = lists:keyfind(?STANDARD_HANDLER,1,Hs), info = maps:get(level,StdC), StdFilters = maps:get(filters,StdC), - {domain,{_,{log,prefix_of,[beam,erlang,otp,sasl]}}} = + {domain,{_,{log,super,[beam,erlang,otp,sasl]}}} = lists:keyfind(domain,1,StdFilters), true = lists:keymember(stop_progress,1,StdFilters), false = lists:keymember(logger_simple,1,Hs), @@ -95,7 +95,7 @@ default_sasl_compatible(Config) -> {?STANDARD_HANDLER,logger_std_h,StdC} = lists:keyfind(?STANDARD_HANDLER,1,Hs), info = maps:get(level,StdC), StdFilters = maps:get(filters,StdC), - {domain,{_,{log,prefix_of,[beam,erlang,otp]}}} = + {domain,{_,{log,super,[beam,erlang,otp]}}} = lists:keyfind(domain,1,StdFilters), false = lists:keymember(stop_progress,1,StdFilters), false = lists:keymember(logger_simple,1,Hs), @@ -107,7 +107,7 @@ error_logger_tty(Config) -> {?STANDARD_HANDLER,logger_std_h,StdC} = lists:keyfind(?STANDARD_HANDLER,1,Hs), info = maps:get(level,StdC), StdFilters = maps:get(filters,StdC), - {domain,{_,{log,prefix_of,[beam,erlang,otp,sasl]}}} = + {domain,{_,{log,super,[beam,erlang,otp,sasl]}}} = lists:keyfind(domain,1,StdFilters), true = lists:keymember(stop_progress,1,StdFilters), false = lists:keymember(logger_simple,1,Hs), @@ -121,7 +121,7 @@ error_logger_tty_sasl_compatible(Config) -> {?STANDARD_HANDLER,logger_std_h,StdC} = lists:keyfind(?STANDARD_HANDLER,1,Hs), info = maps:get(level,StdC), StdFilters = maps:get(filters,StdC), - {domain,{_,{log,prefix_of,[beam,erlang,otp]}}} = + {domain,{_,{log,super,[beam,erlang,otp]}}} = lists:keyfind(domain,1,StdFilters), false = lists:keymember(stop_progress,1,StdFilters), false = lists:keymember(logger_simple,1,Hs), @@ -138,7 +138,7 @@ error_logger_false(Config) -> info = maps:get(level,SimpleC), notice = maps:get(level,L), SimpleFilters = maps:get(filters,SimpleC), - {domain,{_,{log,prefix_of,[beam,erlang,otp,sasl]}}} = + {domain,{_,{log,super,[beam,erlang,otp,sasl]}}} = lists:keyfind(domain,1,SimpleFilters), true = lists:keymember(stop_progress,1,SimpleFilters), false = lists:keymember(sasl_h,1,Hs), @@ -155,7 +155,7 @@ error_logger_false_progress(Config) -> info = maps:get(level,SimpleC), notice = maps:get(level,L), SimpleFilters = maps:get(filters,SimpleC), - {domain,{_,{log,prefix_of,[beam,erlang,otp,sasl]}}} = + {domain,{_,{log,super,[beam,erlang,otp,sasl]}}} = lists:keyfind(domain,1,SimpleFilters), false = lists:keymember(stop_progress,1,SimpleFilters), false = lists:keymember(sasl_h,1,Hs), @@ -172,7 +172,7 @@ error_logger_false_sasl_compatible(Config) -> info = maps:get(level,SimpleC), notice = maps:get(level,L), SimpleFilters = maps:get(filters,SimpleC), - {domain,{_,{log,prefix_of,[beam,erlang,otp]}}} = + {domain,{_,{log,super,[beam,erlang,otp]}}} = lists:keyfind(domain,1,SimpleFilters), false = lists:keymember(stop_progress,1,SimpleFilters), true = lists:keymember(sasl_h,1,Hs), @@ -220,7 +220,7 @@ logger_file(Config) -> {?STANDARD_HANDLER,logger_std_h,StdC} = lists:keyfind(?STANDARD_HANDLER,1,Hs), info = maps:get(level,StdC), StdFilters = maps:get(filters,StdC), - {domain,{_,{log,prefix_of,[beam,erlang,otp,sasl]}}} = + {domain,{_,{log,super,[beam,erlang,otp,sasl]}}} = lists:keyfind(domain,1,StdFilters), true = lists:keymember(stop_progress,1,StdFilters), false = lists:keymember(logger_simple,1,Hs), @@ -243,7 +243,7 @@ logger_file_sasl_compatible(Config) -> {?STANDARD_HANDLER,logger_std_h,StdC} = lists:keyfind(?STANDARD_HANDLER,1,Hs), info = maps:get(level,StdC), StdFilters = maps:get(filters,StdC), - {domain,{_,{log,prefix_of,[beam,erlang,otp]}}} = + {domain,{_,{log,super,[beam,erlang,otp]}}} = lists:keyfind(domain,1,StdFilters), false = lists:keymember(stop_progress,1,StdFilters), false = lists:keymember(logger_simple,1,Hs), @@ -266,7 +266,7 @@ logger_file_log_progress(Config) -> {?STANDARD_HANDLER,logger_std_h,StdC} = lists:keyfind(?STANDARD_HANDLER,1,Hs), info = maps:get(level,StdC), StdFilters = maps:get(filters,StdC), - {domain,{_,{log,prefix_of,[beam,erlang,otp,sasl]}}} = + {domain,{_,{log,super,[beam,erlang,otp,sasl]}}} = lists:keyfind(domain,1,StdFilters), false = lists:keymember(stop_progress,1,StdFilters), false = lists:keymember(logger_simple,1,Hs), @@ -353,7 +353,7 @@ logger_filters(Config) -> {?STANDARD_HANDLER,logger_std_h,StdC} = lists:keyfind(?STANDARD_HANDLER,1,Hs), info = maps:get(level,StdC), StdFilters = maps:get(filters,StdC), - {domain,{_,{log,prefix_of,[beam,erlang,otp,sasl]}}} = + {domain,{_,{log,super,[beam,erlang,otp,sasl]}}} = lists:keyfind(domain,1,StdFilters), false = lists:keymember(stop_progress,1,StdFilters), false = lists:keymember(logger_simple,1,Hs), @@ -406,7 +406,7 @@ logger_module_level(Config) -> {?STANDARD_HANDLER,logger_std_h,StdC} = lists:keyfind(?STANDARD_HANDLER,1,Hs), info = maps:get(level,StdC), StdFilters = maps:get(filters,StdC), - {domain,{_,{log,prefix_of,[beam,erlang,otp,sasl]}}} = + {domain,{_,{log,super,[beam,erlang,otp,sasl]}}} = lists:keyfind(domain,1,StdFilters), false = lists:keymember(stop_progress,1,StdFilters), false = lists:keymember(logger_simple,1,Hs), @@ -428,7 +428,7 @@ logger_disk_log(Config) -> {?STANDARD_HANDLER,logger_disk_log_h,StdC} = lists:keyfind(?STANDARD_HANDLER,1,Hs), info = maps:get(level,StdC), StdFilters = maps:get(filters,StdC), - {domain,{_,{log,prefix_of,[beam,erlang,otp,sasl]}}} = + {domain,{_,{log,super,[beam,erlang,otp,sasl]}}} = lists:keyfind(domain,1,StdFilters), true = lists:keymember(stop_progress,1,StdFilters), false = lists:keymember(logger_simple,1,Hs), @@ -465,7 +465,7 @@ logger_undefined(Config) -> info = maps:get(level,SimpleC), info = maps:get(level,L), SimpleFilters = maps:get(filters,SimpleC), - {domain,{_,{log,prefix_of,[beam,erlang,otp,sasl]}}} = + {domain,{_,{log,super,[beam,erlang,otp,sasl]}}} = lists:keyfind(domain,1,SimpleFilters), true = lists:keymember(stop_progress,1,SimpleFilters), false = lists:keymember(sasl_h,1,Hs), diff --git a/lib/kernel/test/logger_filters_SUITE.erl b/lib/kernel/test/logger_filters_SUITE.erl index c4b31370ff..11cce8fd20 100644 --- a/lib/kernel/test/logger_filters_SUITE.erl +++ b/lib/kernel/test/logger_filters_SUITE.erl @@ -75,79 +75,79 @@ all() -> remote_gl]. domain(_Config) -> - L1 = logger_filters:domain(L1=?dlog([]),{log,prefix_of,[]}), - stop = logger_filters:domain(?dlog([]),{stop,prefix_of,[]}), - L2 = logger_filters:domain(L2=?dlog([]),{log,starts_with,[]}), - stop = logger_filters:domain(?dlog([]),{stop,starts_with,[]}), - L3 = logger_filters:domain(L3=?dlog([]),{log,equals,[]}), - stop = logger_filters:domain(?dlog([]),{stop,equals,[]}), - ignore = logger_filters:domain(?dlog([]),{log,differs,[]}), - ignore = logger_filters:domain(?dlog([]),{stop,differs,[]}), - ignore = logger_filters:domain(?dlog([]),{log,no_domain,[]}), - ignore = logger_filters:domain(?dlog([]),{stop,no_domain,[]}), - - L4 = logger_filters:domain(L4=?dlog([a]),{log,prefix_of,[a,b]}), - stop = logger_filters:domain(?dlog([a]),{stop,prefix_of,[a,b]}), - ignore = logger_filters:domain(?dlog([a]),{log,starts_with,[a,b]}), - ignore = logger_filters:domain(?dlog([a]),{stop,starts_with,[a,b]}), - ignore = logger_filters:domain(?dlog([a]),{log,equals,[a,b]}), - ignore = logger_filters:domain(?dlog([a]),{stop,equals,[a,b]}), - L5 = logger_filters:domain(L5=?dlog([a]),{log,differs,[a,b]}), - stop = logger_filters:domain(?dlog([a]),{stop,differs,[a,b]}), - ignore = logger_filters:domain(?dlog([a]),{log,no_domain,[a,b]}), - ignore = logger_filters:domain(?dlog([a]),{stop,no_domain,[a,b]}), - - ignore = logger_filters:domain(?dlog([a,b]),{log,prefix_of,[a]}), - ignore = logger_filters:domain(?dlog([a,b]),{stop,prefix_of,[a]}), - L6 = logger_filters:domain(L6=?dlog([a,b]),{log,starts_with,[a]}), - stop = logger_filters:domain(?dlog([a,b]),{stop,starts_with,[a]}), - ignore = logger_filters:domain(?dlog([a,b]),{log,equals,[a]}), - ignore = logger_filters:domain(?dlog([a,b]),{stop,equals,[a]}), - L7 = logger_filters:domain(L7=?dlog([a,b]),{log,differs,[a]}), - stop = logger_filters:domain(?dlog([a,b]),{stop,differs,[a]}), - ignore = logger_filters:domain(?dlog([a,b]),{log,no_domain,[a]}), - ignore = logger_filters:domain(?dlog([a,b]),{stop,no_domain,[a]}), - - ignore = logger_filters:domain(?ndlog,{log,prefix_of,[a]}), - ignore = logger_filters:domain(?ndlog,{stop,prefix_of,[a]}), - ignore = logger_filters:domain(?ndlog,{log,starts_with,[a]}), - ignore = logger_filters:domain(?ndlog,{stop,starts_with,[a]}), - ignore = logger_filters:domain(?ndlog,{log,equals,[a]}), - ignore = logger_filters:domain(?ndlog,{stop,equals,[a]}), - L8 = logger_filters:domain(L8=?ndlog,{log,differs,[a]}), - stop = logger_filters:domain(?ndlog,{stop,differs,[a]}), - L9 = logger_filters:domain(L9=?ndlog,{log,no_domain,[a]}), - stop = logger_filters:domain(?ndlog,{stop,no_domain,[a]}), - - L10 = logger_filters:domain(L10=?dlog([a,b,c,d]),{log,prefix_of,[a,b,c,d]}), - stop = logger_filters:domain(?dlog([a,b,c,d]),{stop,prefix_of,[a,b,c,d]}), - L11 = logger_filters:domain(L11=?dlog([a,b,c,d]),{log,starts_with,[a,b,c,d]}), - stop = logger_filters:domain(?dlog([a,b,c,d]),{stop,starts_with,[a,b,c,d]}), - L12 = logger_filters:domain(L12=?dlog([a,b,c,d]),{log,equals,[a,b,c,d]}), - stop = logger_filters:domain(?dlog([a,b,c,d]),{stop,equals,[a,b,c,d]}), - ignore = logger_filters:domain(?dlog([a,b,c,d]),{log,differs,[a,b,c,d]}), - ignore = logger_filters:domain(?dlog([a,b,c,d]),{stop,differs,[a,b,c,d]}), - ignore = logger_filters:domain(?dlog([a,b,c,d]),{log,no_domain,[a,b,c,d]}), - ignore = logger_filters:domain(?dlog([a,b,c,d]),{stop,no_domain,[a,b,c,d]}), + L1 = logger_filters:domain(L1=?dlog([]),{log,super,[]}), + stop = logger_filters:domain(?dlog([]),{stop,super,[]}), + L2 = logger_filters:domain(L2=?dlog([]),{log,sub,[]}), + stop = logger_filters:domain(?dlog([]),{stop,sub,[]}), + L3 = logger_filters:domain(L3=?dlog([]),{log,equal,[]}), + stop = logger_filters:domain(?dlog([]),{stop,equal,[]}), + ignore = logger_filters:domain(?dlog([]),{log,not_equal,[]}), + ignore = logger_filters:domain(?dlog([]),{stop,not_equal,[]}), + ignore = logger_filters:domain(?dlog([]),{log,undefined,[]}), + ignore = logger_filters:domain(?dlog([]),{stop,undefined,[]}), + + L4 = logger_filters:domain(L4=?dlog([a]),{log,super,[a,b]}), + stop = logger_filters:domain(?dlog([a]),{stop,super,[a,b]}), + ignore = logger_filters:domain(?dlog([a]),{log,sub,[a,b]}), + ignore = logger_filters:domain(?dlog([a]),{stop,sub,[a,b]}), + ignore = logger_filters:domain(?dlog([a]),{log,equal,[a,b]}), + ignore = logger_filters:domain(?dlog([a]),{stop,equal,[a,b]}), + L5 = logger_filters:domain(L5=?dlog([a]),{log,not_equal,[a,b]}), + stop = logger_filters:domain(?dlog([a]),{stop,not_equal,[a,b]}), + ignore = logger_filters:domain(?dlog([a]),{log,undefined,[a,b]}), + ignore = logger_filters:domain(?dlog([a]),{stop,undefined,[a,b]}), + + ignore = logger_filters:domain(?dlog([a,b]),{log,super,[a]}), + ignore = logger_filters:domain(?dlog([a,b]),{stop,super,[a]}), + L6 = logger_filters:domain(L6=?dlog([a,b]),{log,sub,[a]}), + stop = logger_filters:domain(?dlog([a,b]),{stop,sub,[a]}), + ignore = logger_filters:domain(?dlog([a,b]),{log,equal,[a]}), + ignore = logger_filters:domain(?dlog([a,b]),{stop,equal,[a]}), + L7 = logger_filters:domain(L7=?dlog([a,b]),{log,not_equal,[a]}), + stop = logger_filters:domain(?dlog([a,b]),{stop,not_equal,[a]}), + ignore = logger_filters:domain(?dlog([a,b]),{log,undefined,[a]}), + ignore = logger_filters:domain(?dlog([a,b]),{stop,undefined,[a]}), + + ignore = logger_filters:domain(?ndlog,{log,super,[a]}), + ignore = logger_filters:domain(?ndlog,{stop,super,[a]}), + ignore = logger_filters:domain(?ndlog,{log,sub,[a]}), + ignore = logger_filters:domain(?ndlog,{stop,sub,[a]}), + ignore = logger_filters:domain(?ndlog,{log,equal,[a]}), + ignore = logger_filters:domain(?ndlog,{stop,equal,[a]}), + L8 = logger_filters:domain(L8=?ndlog,{log,not_equal,[a]}), + stop = logger_filters:domain(?ndlog,{stop,not_equal,[a]}), + L9 = logger_filters:domain(L9=?ndlog,{log,undefined,[a]}), + stop = logger_filters:domain(?ndlog,{stop,undefined,[a]}), + + L10 = logger_filters:domain(L10=?dlog([a,b,c,d]),{log,super,[a,b,c,d]}), + stop = logger_filters:domain(?dlog([a,b,c,d]),{stop,super,[a,b,c,d]}), + L11 = logger_filters:domain(L11=?dlog([a,b,c,d]),{log,sub,[a,b,c,d]}), + stop = logger_filters:domain(?dlog([a,b,c,d]),{stop,sub,[a,b,c,d]}), + L12 = logger_filters:domain(L12=?dlog([a,b,c,d]),{log,equal,[a,b,c,d]}), + stop = logger_filters:domain(?dlog([a,b,c,d]),{stop,equal,[a,b,c,d]}), + ignore = logger_filters:domain(?dlog([a,b,c,d]),{log,not_equal,[a,b,c,d]}), + ignore = logger_filters:domain(?dlog([a,b,c,d]),{stop,not_equal,[a,b,c,d]}), + ignore = logger_filters:domain(?dlog([a,b,c,d]),{log,undefined,[a,b,c,d]}), + ignore = logger_filters:domain(?dlog([a,b,c,d]),{stop,undefined,[a,b,c,d]}), %% A domain field in meta which is not a list is allowed by the %% filter, but since MatchDomain is always a list of atoms, only - %% Action=differs can ever match. - ignore = logger_filters:domain(?dlog(dummy),{log,prefix_of,[a,b,c,d]}), - ignore = logger_filters:domain(?dlog(dummy),{stop,prefix_of,[a,b,c,d]}), - ignore = logger_filters:domain(?dlog(dummy),{log,starts_with,[a,b,c,d]}), - ignore = logger_filters:domain(?dlog(dummy),{stop,starts_with,[a,b,c,d]}), - ignore = logger_filters:domain(?dlog(dummy),{log,equals,[a,b,c,d]}), - ignore = logger_filters:domain(?dlog(dummy),{stop,equals,[a,b,c,d]}), - L13 = logger_filters:domain(L13=?dlog(dummy),{log,differs,[a,b,c,d]}), - stop = logger_filters:domain(?dlog(dummy),{stop,differs,[a,b,c,d]}), - ignore = logger_filters:domain(?dlog(dummy),{log,no_domain,[a,b,c,d]}), - ignore = logger_filters:domain(?dlog(dummy),{stop,no_domain,[a,b,c,d]}), + %% Action=not_equal can ever match. + ignore = logger_filters:domain(?dlog(dummy),{log,super,[a,b,c,d]}), + ignore = logger_filters:domain(?dlog(dummy),{stop,super,[a,b,c,d]}), + ignore = logger_filters:domain(?dlog(dummy),{log,sub,[a,b,c,d]}), + ignore = logger_filters:domain(?dlog(dummy),{stop,sub,[a,b,c,d]}), + ignore = logger_filters:domain(?dlog(dummy),{log,equal,[a,b,c,d]}), + ignore = logger_filters:domain(?dlog(dummy),{stop,equal,[a,b,c,d]}), + L13 = logger_filters:domain(L13=?dlog(dummy),{log,not_equal,[a,b,c,d]}), + stop = logger_filters:domain(?dlog(dummy),{stop,not_equal,[a,b,c,d]}), + ignore = logger_filters:domain(?dlog(dummy),{log,undefined,[a,b,c,d]}), + ignore = logger_filters:domain(?dlog(dummy),{stop,undefined,[a,b,c,d]}), {error,badarg} = ?TRY(logger_filters:domain(?ndlog,bad)), - {error,badarg} = ?TRY(logger_filters:domain(?ndlog,{bad,prefix_of,[]})), + {error,badarg} = ?TRY(logger_filters:domain(?ndlog,{bad,super,[]})), {error,badarg} = ?TRY(logger_filters:domain(?ndlog,{log,bad,[]})), - {error,badarg} = ?TRY(logger_filters:domain(?ndlog,{log,prefix_of,bad})), + {error,badarg} = ?TRY(logger_filters:domain(?ndlog,{log,super,bad})), ok. diff --git a/lib/kernel/test/logger_legacy_SUITE.erl b/lib/kernel/test/logger_legacy_SUITE.erl index b59f5f7758..cfba35e43f 100644 --- a/lib/kernel/test/logger_legacy_SUITE.erl +++ b/lib/kernel/test/logger_legacy_SUITE.erl @@ -68,13 +68,13 @@ init_per_group(std, Config) -> ok = logger:set_handler_config( error_logger,filters, [{domain,{fun logger_filters:domain/2, - {log,prefix_of,[beam,erlang,otp]}}}]), + {log,super,[beam,erlang,otp]}}}]), Config; init_per_group(sasl, Config) -> ok = logger:set_handler_config( error_logger,filters, [{domain,{fun logger_filters:domain/2, - {log,prefix_of,[beam,erlang,otp,sasl]}}}]), + {log,super,[beam,erlang,otp,sasl]}}}]), %% cth_log_redirect checks if sasl is started before displaying %% any sasl reports - so just to see the real sasl reports in tc diff --git a/lib/sasl/src/sasl.erl b/lib/sasl/src/sasl.erl index 9359bdb30e..57e0c6ca82 100644 --- a/lib/sasl/src/sasl.erl +++ b/lib/sasl/src/sasl.erl @@ -129,15 +129,8 @@ get_mf_maxf() -> add_sasl_logger(undefined, _Level) -> ok; add_sasl_logger(std, undefined) -> ok; add_sasl_logger(Dest, Level) -> - FC0 = #{legacy_header=>true, - single_line=>false, - template=>[{logger_formatter,header},"\n",msg,"\n"]}, - FC = case application:get_env(sasl,utc_log) of - {ok,Bool} when is_boolean(Bool) -> - FC0#{utc=>Bool}; - _ -> - FC0 - end, + FC = #{legacy_header=>true, + single_line=>false}, ok = logger:add_handler(sasl_h,logger_std_h, #{level=>Level, filter_default=>stop, @@ -146,7 +139,7 @@ add_sasl_logger(Dest, Level) -> {fun logger_filters:remote_gl/2,stop}}, {sasl_domain, {fun logger_filters:domain/2, - {log,equals,[beam,erlang,otp,sasl]}}}], + {log,equal,[beam,erlang,otp,sasl]}}}], logger_std_h=>#{type=>Dest}, formatter=>{logger_formatter,FC}}). -- cgit v1.2.3 From ca1bf7a9d915a973203aa046bb9f921c11681ee0 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Mon, 21 May 2018 16:52:23 +0200 Subject: Change handler id for sasl handler from sasl_h to sasl --- lib/kernel/doc/src/kernel_app.xml | 2 +- lib/kernel/doc/src/logger_chapter.xml | 2 +- lib/kernel/test/logger_env_var_SUITE.erl | 40 ++++++++++++++++---------------- lib/sasl/doc/src/sasl_app.xml | 4 ++-- lib/sasl/src/sasl.erl | 4 ++-- 5 files changed, 26 insertions(+), 26 deletions(-) (limited to 'lib') diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml index 5bc423afb6..a9292e7660 100644 --- a/lib/kernel/doc/src/kernel_app.xml +++ b/lib/kernel/doc/src/kernel_app.xml @@ -192,7 +192,7 @@ will not log any progress-, crash-, or supervisor reports. If the SASL application is started, these log events will be sent to a second handler instance - named sasl_h, according to values of the SASL + named sasl, according to values of the SASL configuration parameter sasl_error_logger and sasl_errlog_type, see sasl(6) diff --git a/lib/kernel/doc/src/logger_chapter.xml b/lib/kernel/doc/src/logger_chapter.xml index 34c65be47a..1195808160 100644 --- a/lib/kernel/doc/src/logger_chapter.xml +++ b/lib/kernel/doc/src/logger_chapter.xml @@ -630,7 +630,7 @@ configuration parameters 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.

+ named sasl.

All SASL reports have a metadata field domain=>[beam,erlang,otp,sasl], which can be used, for example, by filters to stop or allow the diff --git a/lib/kernel/test/logger_env_var_SUITE.erl b/lib/kernel/test/logger_env_var_SUITE.erl index 081d4f0a80..6a8a868cc2 100644 --- a/lib/kernel/test/logger_env_var_SUITE.erl +++ b/lib/kernel/test/logger_env_var_SUITE.erl @@ -86,7 +86,7 @@ default(Config) -> lists:keyfind(domain,1,StdFilters), true = lists:keymember(stop_progress,1,StdFilters), false = lists:keymember(logger_simple,1,Hs), - false = lists:keymember(sasl_h,1,Hs), + false = lists:keymember(sasl,1,Hs), ok. default_sasl_compatible(Config) -> @@ -99,7 +99,7 @@ default_sasl_compatible(Config) -> lists:keyfind(domain,1,StdFilters), false = lists:keymember(stop_progress,1,StdFilters), false = lists:keymember(logger_simple,1,Hs), - true = lists:keymember(sasl_h,1,Hs), + true = lists:keymember(sasl,1,Hs), ok. error_logger_tty(Config) -> @@ -111,7 +111,7 @@ error_logger_tty(Config) -> lists:keyfind(domain,1,StdFilters), true = lists:keymember(stop_progress,1,StdFilters), false = lists:keymember(logger_simple,1,Hs), - false = lists:keymember(sasl_h,1,Hs), + false = lists:keymember(sasl,1,Hs), ok. error_logger_tty_sasl_compatible(Config) -> @@ -125,7 +125,7 @@ error_logger_tty_sasl_compatible(Config) -> lists:keyfind(domain,1,StdFilters), false = lists:keymember(stop_progress,1,StdFilters), false = lists:keymember(logger_simple,1,Hs), - true = lists:keymember(sasl_h,1,Hs), + true = lists:keymember(sasl,1,Hs), ok. error_logger_false(Config) -> @@ -141,7 +141,7 @@ error_logger_false(Config) -> {domain,{_,{log,super,[beam,erlang,otp,sasl]}}} = lists:keyfind(domain,1,SimpleFilters), true = lists:keymember(stop_progress,1,SimpleFilters), - false = lists:keymember(sasl_h,1,Hs), + false = lists:keymember(sasl,1,Hs), ok. error_logger_false_progress(Config) -> @@ -158,7 +158,7 @@ error_logger_false_progress(Config) -> {domain,{_,{log,super,[beam,erlang,otp,sasl]}}} = lists:keyfind(domain,1,SimpleFilters), false = lists:keymember(stop_progress,1,SimpleFilters), - false = lists:keymember(sasl_h,1,Hs), + false = lists:keymember(sasl,1,Hs), ok. error_logger_false_sasl_compatible(Config) -> @@ -175,7 +175,7 @@ error_logger_false_sasl_compatible(Config) -> {domain,{_,{log,super,[beam,erlang,otp]}}} = lists:keyfind(domain,1,SimpleFilters), false = lists:keymember(stop_progress,1,SimpleFilters), - true = lists:keymember(sasl_h,1,Hs), + true = lists:keymember(sasl,1,Hs), ok. error_logger_silent(Config) -> @@ -183,7 +183,7 @@ error_logger_silent(Config) -> [{error_logger,silent}]), false = lists:keymember(?STANDARD_HANDLER,1,Hs), false = lists:keymember(logger_simple,1,Hs), - false = lists:keymember(sasl_h,1,Hs), + false = lists:keymember(sasl,1,Hs), ok. error_logger_silent_sasl_compatible(Config) -> @@ -192,7 +192,7 @@ error_logger_silent_sasl_compatible(Config) -> {logger_sasl_compatible,true}]), false = lists:keymember(?STANDARD_HANDLER,1,Hs), false = lists:keymember(logger_simple,1,Hs), - true = lists:keymember(sasl_h,1,Hs), + true = lists:keymember(sasl,1,Hs), ok. @@ -224,7 +224,7 @@ logger_file(Config) -> lists:keyfind(domain,1,StdFilters), true = lists:keymember(stop_progress,1,StdFilters), false = lists:keymember(logger_simple,1,Hs), - false = lists:keymember(sasl_h,1,Hs), + false = lists:keymember(sasl,1,Hs), ok. @@ -247,7 +247,7 @@ logger_file_sasl_compatible(Config) -> lists:keyfind(domain,1,StdFilters), false = lists:keymember(stop_progress,1,StdFilters), false = lists:keymember(logger_simple,1,Hs), - true = lists:keymember(sasl_h,1,Hs), + true = lists:keymember(sasl,1,Hs), ok. @@ -270,7 +270,7 @@ logger_file_log_progress(Config) -> lists:keyfind(domain,1,StdFilters), false = lists:keymember(stop_progress,1,StdFilters), false = lists:keymember(logger_simple,1,Hs), - false = lists:keymember(sasl_h,1,Hs), + false = lists:keymember(sasl,1,Hs), ok. @@ -290,7 +290,7 @@ logger_file_no_filter(Config) -> info = maps:get(level,StdC), [] = maps:get(filters,StdC), false = lists:keymember(logger_simple,1,Hs), - false = lists:keymember(sasl_h,1,Hs), + false = lists:keymember(sasl,1,Hs), ok. @@ -311,7 +311,7 @@ logger_file_no_filter_level(Config) -> error = maps:get(level,StdC), [] = maps:get(filters,StdC), false = lists:keymember(logger_simple,1,Hs), - false = lists:keymember(sasl_h,1,Hs), + false = lists:keymember(sasl,1,Hs), ok. @@ -332,7 +332,7 @@ logger_file_formatter(Config) -> info = maps:get(level,StdC), [] = maps:get(filters,StdC), false = lists:keymember(logger_simple,1,Hs), - false = lists:keymember(sasl_h,1,Hs), + false = lists:keymember(sasl,1,Hs), ok. @@ -357,7 +357,7 @@ logger_filters(Config) -> lists:keyfind(domain,1,StdFilters), false = lists:keymember(stop_progress,1,StdFilters), false = lists:keymember(logger_simple,1,Hs), - false = lists:keymember(sasl_h,1,Hs), + false = lists:keymember(sasl,1,Hs), LoggerFilters = maps:get(filters,Logger), true = lists:keymember(stop_progress,1,LoggerFilters), @@ -410,7 +410,7 @@ logger_module_level(Config) -> lists:keyfind(domain,1,StdFilters), false = lists:keymember(stop_progress,1,StdFilters), false = lists:keymember(logger_simple,1,Hs), - false = lists:keymember(sasl_h,1,Hs), + false = lists:keymember(sasl,1,Hs), [{supervisor,error}] = ModuleLevels, ok. @@ -432,7 +432,7 @@ logger_disk_log(Config) -> lists:keyfind(domain,1,StdFilters), true = lists:keymember(stop_progress,1,StdFilters), false = lists:keymember(logger_simple,1,Hs), - false = lists:keymember(sasl_h,1,Hs), + false = lists:keymember(sasl,1,Hs), ok. @@ -453,7 +453,7 @@ logger_disk_log_formatter(Config) -> info = maps:get(level,StdC), [] = maps:get(filters,StdC), false = lists:keymember(logger_simple,1,Hs), - false = lists:keymember(sasl_h,1,Hs), + false = lists:keymember(sasl,1,Hs), ok. @@ -468,7 +468,7 @@ logger_undefined(Config) -> {domain,{_,{log,super,[beam,erlang,otp,sasl]}}} = lists:keyfind(domain,1,SimpleFilters), true = lists:keymember(stop_progress,1,SimpleFilters), - false = lists:keymember(sasl_h,1,Hs), + false = lists:keymember(sasl,1,Hs), ok. diff --git a/lib/sasl/doc/src/sasl_app.xml b/lib/sasl/doc/src/sasl_app.xml index eb1e87d9a3..0a9e6483f0 100644 --- a/lib/sasl/doc/src/sasl_app.xml +++ b/lib/sasl/doc/src/sasl_app.xml @@ -133,10 +133,10 @@ obtained by setting the Kernel application environment variable logger_sasl_compatible=true. This will add a second instance of the standard logger handler - named sasl_h, which will only print the SASL reports. No + named sasl, which will only print the SASL reports. No SASL reports will then be printed by the Kernel logger handler.

-

The sasl_h handler will be configured according to the +

The sasl handler will be configured according to the values of the following SASL application environment variables.

diff --git a/lib/sasl/src/sasl.erl b/lib/sasl/src/sasl.erl index 57e0c6ca82..92b80694d7 100644 --- a/lib/sasl/src/sasl.erl +++ b/lib/sasl/src/sasl.erl @@ -131,7 +131,7 @@ add_sasl_logger(std, undefined) -> ok; add_sasl_logger(Dest, Level) -> FC = #{legacy_header=>true, single_line=>false}, - ok = logger:add_handler(sasl_h,logger_std_h, + ok = logger:add_handler(sasl,logger_std_h, #{level=>Level, filter_default=>stop, filters=> @@ -146,7 +146,7 @@ add_sasl_logger(Dest, Level) -> delete_sasl_logger(undefined) -> ok; delete_sasl_logger(std) -> ok; delete_sasl_logger(_Type) -> - _ = logger:remove_handler(sasl_h), + _ = logger:remove_handler(sasl), ok. add_error_logger_mf(undefined) -> ok; -- cgit v1.2.3 From f38163aa64547e09f99e362edefeda713e06ddb7 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Mon, 21 May 2018 17:45:21 +0200 Subject: Remove HandlerId from handler callback functions and add it to Config --- lib/kernel/doc/src/logger.xml | 23 +++++++++++++---------- lib/kernel/doc/src/logger_chapter.xml | 26 +++++++++++++------------- lib/kernel/src/error_logger.erl | 10 +++++----- lib/kernel/src/logger.erl | 3 ++- lib/kernel/src/logger_disk_log_h.erl | 25 +++++++++++-------------- lib/kernel/src/logger_server.erl | 13 +++++++------ lib/kernel/src/logger_simple.erl | 6 +++--- lib/kernel/src/logger_std_h.erl | 25 +++++++++++-------------- lib/kernel/test/logger_SUITE.erl | 12 ++++++------ 9 files changed, 71 insertions(+), 72 deletions(-) (limited to 'lib') diff --git a/lib/kernel/doc/src/logger.xml b/lib/kernel/doc/src/logger.xml index 6e50473fa8..d6576db6f3 100644 --- a/lib/kernel/doc/src/logger.xml +++ b/lib/kernel/doc/src/logger.xml @@ -881,11 +881,9 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(),Meta)). - HModule:adding_handler(HandlerId,Config1) -> {ok,Config2} | {error,Reason} + HModule:adding_handler(Config1) -> {ok,Config2} | {error,Reason} An instance of this handler is about to be added. - HandlerId = - handler_id() Config1 = Config2 = config() Reason = term() @@ -895,6 +893,8 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(),Meta)).

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

+

The handler identity is associated with the id key + in Config1.

If everything succeeds, the callback function can add possible default values or internal state values to the configuration, and return the adjusted map @@ -905,11 +905,9 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(),Meta)). - HModule:changing_config(HandlerId,Config1,Config2) -> {ok,Config3} | {error,Reason} + HModule:changing_config(Config1,Config2) -> {ok,Config3} | {error,Reason} The configuration for this handler is about to change. - HandlerId = - handler_id() Config1 = Config2 = Config3 = config() Reason = term() @@ -921,6 +919,8 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(),Meta)). the new configuration.

Config1 is the existing configuration and Config2 is the new configuration.

+

The handler identity is associated with the id key + in Config1.

If everything succeeds, the callback function must return a possibly adjusted configuration in {ok,Config3}.

If the configuration is faulty, the callback function must @@ -942,6 +942,8 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(),Meta)).

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 identity is associated with the id key + in Config.

The handler must log the event.

The return value from this function is ignored by Logger.

@@ -949,11 +951,9 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(),Meta)).
- HModule:removing_handler(HandlerId,Config) -> ok + HModule:removing_handler(Config) -> ok The given handler is about to be removed. - HandlerId = - handler_id() Config = config() @@ -961,7 +961,10 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(),Meta)).

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.

+ the handler.

+

The handler identity is associated with the id key + in Config.

+

The return value is ignored by Logger.

diff --git a/lib/kernel/doc/src/logger_chapter.xml b/lib/kernel/doc/src/logger_chapter.xml index 1195808160..78c595d521 100644 --- a/lib/kernel/doc/src/logger_chapter.xml +++ b/lib/kernel/doc/src/logger_chapter.xml @@ -268,7 +268,7 @@

In addition to the mandatory callback function log/2, a handler module can export the optional callback - functions adding_handler/2, changing_config/3 + functions adding_handler/1, changing_config/2 and removing_handler/1. See section Handler Callback Functions in the logger(3) manual for more @@ -738,22 +738,22 @@ ok 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(),logger:config()) -> ok -changing_config(logger:handler_id(),logger:config(),logger:config()) -> {ok,logger:config()} | {error,term()} +adding_handler(logger:config()) -> {ok,logger:config()} | {error,term()} +removing_handler(logger:config()) -> ok +changing_config(logger:config(),logger:config()) -> {ok,logger:config()} | {error,term()}

When logger:add_handler(Id,Module,Config) is called, Logger - will first call HModule:adding_handler(Id,Config), and if it + will first call HModule:adding_handler(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 HModule:log/2.

A handler can be removed by calling logger:remove_handler(Id). Logger will call - HModule:removing_handler(Id,Config), and then remove the + HModule:removing_handler(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 HModule:changing_config(Id,OldConfig,NewConfig). If + calls HModule:changing_config(OldConfig,NewConfig). If this function returns {ok,NewConfig}, NewConfig is written to the configuration database.

@@ -771,14 +771,14 @@ log(Log,#{formatter:={FModule,FConfig}) -> this:

-module(myhandler). --export([adding_handler/2, removing_handler/2, log/2]). +-export([adding_handler/1, removing_handler/1, log/2]). -export([init/1, handle_call/3, handle_cast/2, terminate/2]). -adding_handler(Id,Config) -> +adding_handler(Config) -> {ok,Fd} = file:open(File,[append,{encoding,utf8}]), {ok,Config#{myhandler_fd=>Fd}}. -removing_handler(Id,#{myhandler_fd:=Fd}) -> +removing_handler(#{myhandler_fd:=Fd}) -> _ = file:close(Fd), ok. @@ -800,14 +800,14 @@ log(Log,#{myhandler_fd:=Fd,formatter:={FModule,FConfig}}) -> single process.

-module(myhandler). --export([adding_handler/2, removing_handler/2, log/2]). +-export([adding_handler/1, removing_handler/1, log/2]). -export([init/1, handle_call/3, handle_cast/2, terminate/2]). -adding_handler(Id,Config) -> +adding_handler(Config) -> {ok,Pid} = gen_server:start(?MODULE,Config), {ok,Config#{myhandler_pid=>Pid}}. -removing_handler(Id,#{myhandler_pid:=Pid}) -> +removing_handler(#{myhandler_pid:=Pid}) -> gen_server:stop(Pid). log(Log,#{myhandler_pid:=Pid} = Config) -> diff --git a/lib/kernel/src/error_logger.erl b/lib/kernel/src/error_logger.erl index 6c3b308308..96f6536e61 100644 --- a/lib/kernel/src/error_logger.erl +++ b/lib/kernel/src/error_logger.erl @@ -32,7 +32,7 @@ which_report_handlers/0]). %% logger callbacks --export([adding_handler/2, removing_handler/2, log/2]). +-export([adding_handler/1, removing_handler/1, log/2]). -export([get_format_depth/0, limit_term/1]). @@ -101,9 +101,9 @@ stop() -> %%%----------------------------------------------------------------- %%% Callbacks for logger --spec adding_handler(logger:handler_id(),logger:config()) -> +-spec adding_handler(logger:config()) -> {ok,logger:config()} | {error,term()}. -adding_handler(?MODULE,Config) -> +adding_handler(#{id:=?MODULE}=Config) -> case start() of ok -> {ok,Config}; @@ -111,8 +111,8 @@ adding_handler(?MODULE,Config) -> Error end. --spec removing_handler(logger:handler_id(),logger:config()) -> ok. -removing_handler(?MODULE,_Config) -> +-spec removing_handler(logger:config()) -> ok. +removing_handler(#{id:=?MODULE}) -> stop(), ok. diff --git a/lib/kernel/src/logger.erl b/lib/kernel/src/logger.erl index 9c721d7fee..f22fd5e8de 100644 --- a/lib/kernel/src/logger.erl +++ b/lib/kernel/src/logger.erl @@ -90,7 +90,8 @@ -type filter() :: {fun((log(),filter_arg()) -> filter_return()),filter_arg()}. -type filter_arg() :: term(). -type filter_return() :: stop | ignore | log(). --type config() :: #{level => level(), +-type config() :: #{id => handler_id(), + level => level(), filter_default => log | stop, filters => [{filter_id(),filter()}], formatter => {module(),formatter_config()}, diff --git a/lib/kernel/src/logger_disk_log_h.erl b/lib/kernel/src/logger_disk_log_h.erl index 57c54ce27e..37a147e3dc 100644 --- a/lib/kernel/src/logger_disk_log_h.erl +++ b/lib/kernel/src/logger_disk_log_h.erl @@ -34,8 +34,8 @@ %% logger callbacks -export([log/2, - adding_handler/2, removing_handler/2, - changing_config/3, swap_buffer/2]). + adding_handler/1, removing_handler/1, + changing_config/2, swap_buffer/2]). %%%=================================================================== %%% API @@ -108,8 +108,8 @@ reset(Name) -> %%%----------------------------------------------------------------- %%% Handler being added -adding_handler(Name, Config) -> - case check_config(adding, Name, Config) of +adding_handler(#{id:=Name}=Config) -> + case check_config(adding, Config) of {ok, Config1} -> %% create initial handler state by merging defaults with config HConfig = maps:get(?MODULE, Config1, #{}), @@ -136,10 +136,9 @@ adding_handler(Name, Config) -> %%%----------------------------------------------------------------- %%% Updating handler config -changing_config(Name, - OldConfig=#{id:=Id, disk_log_opts:=DLOpts}, - NewConfig=#{id:=Id, disk_log_opts:=DLOpts}) -> - case check_config(changing, Name, NewConfig) of +changing_config(OldConfig=#{id:=Name, disk_log_opts:=DLOpts}, + NewConfig=#{id:=Name, disk_log_opts:=DLOpts}) -> + case check_config(changing, NewConfig) of Result = {ok,NewConfig1} -> try gen_server:call(Name, {change_config,OldConfig,NewConfig1}, ?DEFAULT_CALL_TIMEOUT) of @@ -151,12 +150,10 @@ changing_config(Name, Error -> Error end; -changing_config(_Name, OldConfig, NewConfig) -> +changing_config(OldConfig, NewConfig) -> {error,{illegal_config_change,OldConfig,NewConfig}}. -check_config(adding, Name, Config0) -> - %% Merge in defaults on top level - Config = maps:merge(#{id => Name}, Config0), +check_config(adding, #{id:=Name}=Config) -> %% Merge in defaults on handler level LogOpts0 = maps:get(disk_log_opts, Config, #{}), LogOpts = merge_default_logopts(Name, LogOpts0), @@ -173,7 +170,7 @@ check_config(adding, Name, Config0) -> Error -> Error end; -check_config(changing, _Name, Config) -> +check_config(changing, Config) -> MyConfig = maps:get(?MODULE, Config, #{}), case check_my_config(maps:to_list(MyConfig)) of ok -> {ok,Config}; @@ -223,7 +220,7 @@ check_my_config([]) -> %%%----------------------------------------------------------------- %%% Handler being removed -removing_handler(Name, _Config) -> +removing_handler(#{id:=Name}) -> stop(Name). %%%----------------------------------------------------------------- diff --git a/lib/kernel/src/logger_server.erl b/lib/kernel/src/logger_server.erl index 16f61abdd6..9182b0b486 100644 --- a/lib/kernel/src/logger_server.erl +++ b/lib/kernel/src/logger_server.erl @@ -134,7 +134,7 @@ init([]) -> filters=>?DEFAULT_HANDLER_FILTERS}), %% If this fails, then the node should crash {ok,SimpleConfig} = - logger_simple:adding_handler(logger_simple,SimpleConfig0), + logger_simple:adding_handler(SimpleConfig0), logger_config:create(Tid,logger_simple,logger_simple,SimpleConfig), {ok, #state{tid=Tid, async_req_queue = queue:new()}}. @@ -146,7 +146,7 @@ handle_call({add_handler,Id,Module,HConfig}, From, #state{tid=Tid}=State) -> call_h_async( fun() -> %% inform the handler - call_h(Module,adding_handler,[Id,HConfig],{ok,HConfig}) + call_h(Module,adding_handler,[HConfig],{ok,HConfig}) end, fun({ok,HConfig1}) -> %% We know that the call_h would have loaded the module @@ -177,7 +177,7 @@ handle_call({remove_handler,HandlerId}, From, #state{tid=Tid}=State) -> call_h_async( fun() -> %% inform the handler - call_h(Module,removing_handler,[HandlerId,HConfig],ok) + call_h(Module,removing_handler,[HConfig],ok) end, fun(_Res) -> do_set_config(Tid,logger,Config#{handlers=>Handlers}), @@ -213,7 +213,7 @@ handle_call({set_config,HandlerId,Config}, From, #state{tid=Tid}=State) -> {ok,{Module,OldConfig}} -> call_h_async( fun() -> - call_h(Module,changing_config,[HandlerId,OldConfig,Config], + call_h(Module,changing_config,[OldConfig,Config], {ok,Config}) end, fun({ok,Config1}) -> @@ -348,8 +348,9 @@ default_config(logger) -> #{level=>info, filters=>[], filter_default=>log}; -default_config(_) -> - #{level=>info, +default_config(Id) -> + #{id=>Id, + level=>info, filters=>[], filter_default=>log, formatter=>{?DEFAULT_FORMATTER,#{}}}. diff --git a/lib/kernel/src/logger_simple.erl b/lib/kernel/src/logger_simple.erl index c8cdf25887..cfb3fcb620 100644 --- a/lib/kernel/src/logger_simple.erl +++ b/lib/kernel/src/logger_simple.erl @@ -19,7 +19,7 @@ %% -module(logger_simple). --export([adding_handler/2, removing_handler/2, log/2]). +-export([adding_handler/1, removing_handler/1, log/2]). %% This module implements a simple handler for logger. It is the %% default used during system start. @@ -27,7 +27,7 @@ %%%----------------------------------------------------------------- %%% Logger callback -adding_handler(?MODULE,Config) -> +adding_handler(#{id:=?MODULE}=Config) -> Me = self(), case whereis(?MODULE) of undefined -> @@ -44,7 +44,7 @@ adding_handler(?MODULE,Config) -> {error,{handler_process_name_already_exists,?MODULE}} end. -removing_handler(?MODULE,_Config) -> +removing_handler(#{id:=?MODULE}) -> case whereis(?MODULE) of undefined -> ok; diff --git a/lib/kernel/src/logger_std_h.erl b/lib/kernel/src/logger_std_h.erl index e5e0febc88..fc8ca1535b 100644 --- a/lib/kernel/src/logger_std_h.erl +++ b/lib/kernel/src/logger_std_h.erl @@ -35,8 +35,8 @@ terminate/2, code_change/3]). %% logger callbacks --export([log/2, adding_handler/2, removing_handler/2, - changing_config/3, swap_buffer/2]). +-export([log/2, adding_handler/1, removing_handler/1, + changing_config/2, swap_buffer/2]). %%%=================================================================== %%% API @@ -109,8 +109,8 @@ reset(Name) -> %%%----------------------------------------------------------------- %%% Handler being added -adding_handler(Name, Config) -> - case check_config(adding, Name, Config) of +adding_handler(#{id:=Name}=Config) -> + case check_config(adding, Config) of {ok, Config1} -> %% create initial handler state by merging defaults with config HConfig = maps:get(?MODULE, Config1, #{}), @@ -137,9 +137,8 @@ adding_handler(Name, Config) -> %%%----------------------------------------------------------------- %%% Updating handler config -changing_config(Name, - OldConfig=#{id:=Id, ?MODULE:=#{type:=Type}}, - NewConfig=#{id:=Id}) -> +changing_config(OldConfig=#{id:=Name, ?MODULE:=#{type:=Type}}, + NewConfig=#{id:=Name}) -> MyConfig = maps:get(?MODULE, NewConfig, #{}), case maps:get(type, MyConfig, Type) of Type -> @@ -149,11 +148,11 @@ changing_config(Name, _ -> {error,{illegal_config_change,OldConfig,NewConfig}} end; -changing_config(_Name, OldConfig, NewConfig) -> +changing_config(OldConfig, NewConfig) -> {error,{illegal_config_change,OldConfig,NewConfig}}. changing_config1(Name, OldConfig, NewConfig) -> - case check_config(changing, Name, NewConfig) of + case check_config(changing, NewConfig) of Result = {ok,NewConfig1} -> try gen_server:call(Name, {change_config,OldConfig,NewConfig1}, ?DEFAULT_CALL_TIMEOUT) of @@ -166,9 +165,7 @@ changing_config1(Name, OldConfig, NewConfig) -> Error end. -check_config(adding, Name, Config0) -> - %% Merge in defaults on top level - Config = maps:merge(#{id => Name}, Config0), +check_config(adding, Config) -> %% Merge in defaults on handler level MyConfig0 = maps:get(?MODULE, Config, #{}), MyConfig = maps:merge(#{type => standard_io}, @@ -179,7 +176,7 @@ check_config(adding, Name, Config0) -> Error -> Error end; -check_config(changing, _Name, Config) -> +check_config(changing, Config) -> MyConfig = maps:get(?MODULE, Config, #{}), case check_my_config(maps:to_list(MyConfig)) of ok -> {ok,Config}; @@ -207,7 +204,7 @@ check_my_config([]) -> %%%----------------------------------------------------------------- %%% Handler being removed -removing_handler(Name,_Config) -> +removing_handler(#{id:=Name}) -> stop(Name). %%%----------------------------------------------------------------- diff --git a/lib/kernel/test/logger_SUITE.erl b/lib/kernel/test/logger_SUITE.erl index 66eee8219a..f7ec59a7b7 100644 --- a/lib/kernel/test/logger_SUITE.erl +++ b/lib/kernel/test/logger_SUITE.erl @@ -839,20 +839,20 @@ check_maps(Expected,Got,What) -> end. %% Handler -adding_handler(_Id,#{add_call:=Fun}) -> +adding_handler(#{add_call:=Fun}) -> Fun(); -adding_handler(_Id,Config) -> +adding_handler(Config) -> maybe_send(add), {ok,Config}. -removing_handler(_Id,#{rem_call:=Fun}) -> +removing_handler(#{rem_call:=Fun}) -> Fun(); -removing_handler(_Id,_Config) -> +removing_handler(_Config) -> maybe_send(remove), ok. -changing_config(_Id,_Old,#{conf_call:=Fun}) -> +changing_config(_Old,#{conf_call:=Fun}) -> Fun(); -changing_config(_Id,_Old,Config) -> +changing_config(_Old,Config) -> maybe_send(changing_config), {ok,Config}. -- cgit v1.2.3 From 51c6464a011eacd78340b60e2641eaecc36933f6 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Mon, 21 May 2018 17:59:10 +0200 Subject: Change env var logger_log_progress to logger_progress_reports --- lib/kernel/doc/src/kernel_app.xml | 10 +++++----- lib/kernel/doc/src/logger_chapter.xml | 8 ++++---- lib/kernel/src/kernel.app.src | 2 +- lib/kernel/src/logger.erl | 6 +++--- lib/kernel/test/logger_env_var_SUITE.erl | 16 ++++++++-------- lib/sasl/doc/src/error_logging.xml | 4 ++-- lib/sasl/doc/src/sasl_app.xml | 6 +++--- 7 files changed, 26 insertions(+), 26 deletions(-) (limited to 'lib') diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml index a9292e7660..0f7e95472b 100644 --- a/lib/kernel/doc/src/kernel_app.xml +++ b/lib/kernel/doc/src/kernel_app.xml @@ -204,17 +204,17 @@

This configuration option only effects the default and sasl handler. Any other handlers are uneffected.

- - logger_log_progress = boolean() + + logger_progress_reports = stop | log

If logger_sasl_compatible = false, - then logger_log_progress specifies if progress + then logger_progress_reports specifies if progress reports from supervisor and application_controller shall be logged by the default logger.

If logger_sasl_compatible = true, - then logger_log_progress is ignored.

-

The default value is false

+ then logger_progress_reports is ignored.

+

The default value is stop

This configuration option only effects the default and sasl handler. Any other handlers are uneffected.

diff --git a/lib/kernel/doc/src/logger_chapter.xml b/lib/kernel/doc/src/logger_chapter.xml index 78c595d521..dff9ee2892 100644 --- a/lib/kernel/doc/src/logger_chapter.xml +++ b/lib/kernel/doc/src/logger_chapter.xml @@ -344,8 +344,8 @@ logger, logger_level, logger_sasl_compatible and - logger_log_progress. - logger_level, logger_sasl_compatible and logger_log_progress are described in the + logger_progress_reports. + logger_level, logger_sasl_compatible and logger_progress_reports are described in the Kernel Configuration, while logger is described below.

@@ -617,8 +617,8 @@ default. Progress reports are not logged by default, but can be enabled with the Kernel configuration - parameter - logger_log_progress. + parameter + logger_progress_reports. The output format is the same for all log events. diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src index 23ac5b3444..46fb3e09d5 100644 --- a/lib/kernel/src/kernel.app.src +++ b/lib/kernel/src/kernel.app.src @@ -142,7 +142,7 @@ {applications, []}, {env, [{logger_level, info}, {logger_sasl_compatible, false}, - {logger_log_progress, false} + {logger_progress_reports, stop} ]}, {mod, {kernel, []}}, {runtime_dependencies, ["erts-10.0", "stdlib-3.5", "sasl-3.0"]} diff --git a/lib/kernel/src/logger.erl b/lib/kernel/src/logger.erl index f22fd5e8de..b32fca1fda 100644 --- a/lib/kernel/src/logger.erl +++ b/lib/kernel/src/logger.erl @@ -731,10 +731,10 @@ get_default_handler_filters() -> ?DEFAULT_HANDLER_FILTERS([beam,erlang,otp]); false -> Extra = - case application:get_env(kernel, logger_log_progress, false) of - true -> + case application:get_env(kernel, logger_progress_reports, stop) of + log -> []; - false -> + stop -> [{stop_progress, {fun logger_filters:progress/2,stop}}] end, diff --git a/lib/kernel/test/logger_env_var_SUITE.erl b/lib/kernel/test/logger_env_var_SUITE.erl index 6a8a868cc2..a808a31f17 100644 --- a/lib/kernel/test/logger_env_var_SUITE.erl +++ b/lib/kernel/test/logger_env_var_SUITE.erl @@ -149,7 +149,7 @@ error_logger_false_progress(Config) -> setup(Config, [{error_logger,false}, {logger_level,notice}, - {logger_log_progress,true}]), + {logger_progress_reports,log}]), false = lists:keymember(?STANDARD_HANDLER,1,Hs), {logger_simple,logger_simple,SimpleC} = lists:keyfind(logger_simple,1,Hs), info = maps:get(level,SimpleC), @@ -255,7 +255,7 @@ logger_file_log_progress(Config) -> Log = file(Config,?FUNCTION_NAME), {ok,#{handlers:=Hs},Node} = setup(Config, - [{logger_log_progress,true}, + [{logger_progress_reports,log}, {logger, [{handler,?STANDARD_HANDLER,logger_std_h, #{logger_std_h=>#{type=>{file,Log}}}}]}]), @@ -340,7 +340,7 @@ logger_filters(Config) -> Log = file(Config,?FUNCTION_NAME), {ok,#{handlers:=Hs,logger:=Logger},Node} = setup(Config, - [{logger_log_progress,true}, + [{logger_progress_reports,log}, {logger, [{handler,?STANDARD_HANDLER,logger_std_h, #{logger_std_h=>#{type=>{file,Log}}}}, @@ -367,7 +367,7 @@ logger_filters_stop(Config) -> Log = file(Config,?FUNCTION_NAME), {ok,#{handlers:=Hs,logger:=Logger},Node} = setup(Config, - [{logger_log_progress,true}, + [{logger_progress_reports,log}, {logger, [{handler,?STANDARD_HANDLER,logger_std_h, #{filters=>[], @@ -393,7 +393,7 @@ logger_module_level(Config) -> Log = file(Config,?FUNCTION_NAME), {ok,#{handlers:=Hs,module_levels:=ModuleLevels},Node} = setup(Config, - [{logger_log_progress,true}, + [{logger_progress_reports,log}, {logger, [{handler,?STANDARD_HANDLER,logger_std_h, #{logger_std_h=>#{type=>{file,Log}}}}, @@ -552,7 +552,7 @@ sasl_compatible_false(Config) -> {ok,_Hs,Node} = setup(Config, [{error_logger,{file,Log}}, {logger_sasl_compatible,false}, - {logger_log_progress,true}]), + {logger_progress_reports,log}]), check_default_log(Node,Log, file,% dest 6),% progress in std logger @@ -563,7 +563,7 @@ sasl_compatible_false_no_progress(Config) -> {ok,_Hs,Node} = setup(Config, [{error_logger,{file,Log}}, {logger_sasl_compatible,false}, - {logger_log_progress,false}]), + {logger_progress_reports,stop}]), check_default_log(Node,Log, file,% dest 0),% progress in std logger @@ -589,7 +589,7 @@ bad_sasl_compatibility(Config) -> error = setup(Config,[{logger_sasl_compatible,badcomp}]). bad_progress(Config) -> - error = setup(Config,[{logger_log_progress,badprogress}]). + error = setup(Config,[{logger_progress_reports,badprogress}]). %%%----------------------------------------------------------------- %%% Internal diff --git a/lib/sasl/doc/src/error_logging.xml b/lib/sasl/doc/src/error_logging.xml index 44506ffdad..8731b73599 100644 --- a/lib/sasl/doc/src/error_logging.xml +++ b/lib/sasl/doc/src/error_logging.xml @@ -46,8 +46,8 @@ Kernel. Progress reports are by default not logged, but can be enabled by setting the Kernel configuration - parameter - logger_log_progress to true.

+ parameter + logger_progress_reports to log.

The old SASL error logging behaviour can be re-enabled by setting the Kernel configuration parameter diff --git a/lib/sasl/doc/src/sasl_app.xml b/lib/sasl/doc/src/sasl_app.xml index 0a9e6483f0..7f4ceeb354 100644 --- a/lib/sasl/doc/src/sasl_app.xml +++ b/lib/sasl/doc/src/sasl_app.xml @@ -102,10 +102,10 @@ reports, crash reports, and progress reports. These reports are now also printed by the default logger handler started by the Kernel application. Progress - reports are by default stopped by a filter, but can easily be + reports are by default stopped by a filter, but can be added by setting the Kernel configuration - parameter - logger_log_progress=true.

+ parameter + logger_progress_reports to log.

If the old error logger event handlers are still desired, they must be added by calling error_logger:add_report_handler/1,2.

-- cgit v1.2.3 From 530d3cf99c562e3678eeb08e135ae90c4df4e052 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Thu, 17 May 2018 19:45:50 +0200 Subject: Rename module logger_simple to logger_simple_h Also, change HandlerId from logger_simple to simple. --- lib/kernel/src/Makefile | 4 +- lib/kernel/src/kernel.app.src | 2 +- lib/kernel/src/logger.erl | 10 +- lib/kernel/src/logger_server.erl | 9 +- lib/kernel/src/logger_simple.erl | 212 ------------------------------ lib/kernel/src/logger_simple_h.erl | 212 ++++++++++++++++++++++++++++++ lib/kernel/test/Makefile | 2 +- lib/kernel/test/logger.cover | 2 +- lib/kernel/test/logger.spec | 2 +- lib/kernel/test/logger_env_var_SUITE.erl | 44 +++---- lib/kernel/test/logger_simple_SUITE.erl | 210 ----------------------------- lib/kernel/test/logger_simple_h_SUITE.erl | 210 +++++++++++++++++++++++++++++ lib/sasl/src/systools_make.erl | 2 +- 13 files changed, 460 insertions(+), 461 deletions(-) delete mode 100644 lib/kernel/src/logger_simple.erl create mode 100644 lib/kernel/src/logger_simple_h.erl delete mode 100644 lib/kernel/test/logger_simple_SUITE.erl create mode 100644 lib/kernel/test/logger_simple_h_SUITE.erl (limited to 'lib') diff --git a/lib/kernel/src/Makefile b/lib/kernel/src/Makefile index eeb8c6ab2f..f265fdd272 100644 --- a/lib/kernel/src/Makefile +++ b/lib/kernel/src/Makefile @@ -118,7 +118,7 @@ MODULES = \ logger_filters \ logger_formatter \ logger_server \ - logger_simple \ + logger_simple_h \ logger_sup \ net \ net_adm \ @@ -279,7 +279,7 @@ $(EBIN)/logger_disk_log_h.beam: logger_h_common.hrl logger_internal.hrl ../inclu $(EBIN)/logger_filters.beam: logger_internal.hrl ../include/logger.hrl $(EBIN)/logger_formatter.beam: logger_internal.hrl ../include/logger.hrl $(EBIN)/logger_server.beam: logger_internal.hrl ../include/logger.hrl -$(EBIN)/logger_simple.beam: logger_internal.hrl ../include/logger.hrl +$(EBIN)/logger_simple_h.beam: logger_internal.hrl ../include/logger.hrl $(EBIN)/logger_std_h.beam: logger_h_common.hrl logger_internal.hrl ../include/logger.hrl ../include/file.hrl $(EBIN)/logger_h_common.beam: logger_h_common.hrl logger_internal.hrl ../include/logger.hrl $(EBIN)/net_kernel.beam: ../include/net_address.hrl diff --git a/lib/kernel/src/kernel.app.src b/lib/kernel/src/kernel.app.src index 46fb3e09d5..d873178f55 100644 --- a/lib/kernel/src/kernel.app.src +++ b/lib/kernel/src/kernel.app.src @@ -68,7 +68,7 @@ logger_formatter, logger_h_common, logger_server, - logger_simple, + logger_simple_h, logger_std_h, logger_sup, net, diff --git a/lib/kernel/src/logger.erl b/lib/kernel/src/logger.erl index b32fca1fda..f35036aa04 100644 --- a/lib/kernel/src/logger.erl +++ b/lib/kernel/src/logger.erl @@ -561,10 +561,10 @@ internal_init_logger() -> end || Module <- Modules] || {module_level, Level, Modules} <- get_logger_env()], - case logger:set_handler_config(logger_simple,filters, + case logger:set_handler_config(simple,filters, get_default_handler_filters()) of ok -> ok; - {error,{not_found,logger_simple}} -> ok + {error,{not_found,simple}} -> ok end, init_kernel_handlers() @@ -580,7 +580,7 @@ init_kernel_handlers() -> try case get_logger_type() of {ok,silent} -> - ok = logger:remove_handler(logger_simple); + ok = logger:remove_handler(simple); {ok,false} -> ok; {ok,Type} -> @@ -621,9 +621,9 @@ add_handlers(HandlerConfig) -> %% If a default handler was added we try to remove the simple_logger %% If the simple logger exists it will replay its log events %% to the handler(s) added in the fold above. - _ = [case logger:remove_handler(logger_simple) of + _ = [case logger:remove_handler(simple) of ok -> ok; - {error,{not_found,logger_simple}} -> ok + {error,{not_found,simple}} -> ok end || DefaultAdded], ok catch throw:Reason -> diff --git a/lib/kernel/src/logger_server.erl b/lib/kernel/src/logger_server.erl index 9182b0b486..47010c9fa5 100644 --- a/lib/kernel/src/logger_server.erl +++ b/lib/kernel/src/logger_server.erl @@ -127,15 +127,14 @@ init([]) -> process_flag(trap_exit, true), Tid = logger_config:new(?LOGGER_TABLE), LoggerConfig = maps:merge(default_config(logger), - #{handlers=>[logger_simple]}), + #{handlers=>[simple]}), logger_config:create(Tid,logger,LoggerConfig), - SimpleConfig0 = maps:merge(default_config(logger_simple), + SimpleConfig0 = maps:merge(default_config(simple), #{filter_default=>stop, filters=>?DEFAULT_HANDLER_FILTERS}), %% If this fails, then the node should crash - {ok,SimpleConfig} = - logger_simple:adding_handler(SimpleConfig0), - logger_config:create(Tid,logger_simple,logger_simple,SimpleConfig), + {ok,SimpleConfig} = logger_simple_h:adding_handler(SimpleConfig0), + logger_config:create(Tid,simple,logger_simple_h,SimpleConfig), {ok, #state{tid=Tid, async_req_queue = queue:new()}}. handle_call({add_handler,Id,Module,HConfig}, From, #state{tid=Tid}=State) -> diff --git a/lib/kernel/src/logger_simple.erl b/lib/kernel/src/logger_simple.erl deleted file mode 100644 index cfb3fcb620..0000000000 --- a/lib/kernel/src/logger_simple.erl +++ /dev/null @@ -1,212 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2017. 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. -%% -%% %CopyrightEnd% -%% --module(logger_simple). - --export([adding_handler/1, removing_handler/1, log/2]). - -%% This module implements a simple handler for logger. It is the -%% default used during system start. - -%%%----------------------------------------------------------------- -%%% Logger callback - -adding_handler(#{id:=?MODULE}=Config) -> - Me = self(), - case whereis(?MODULE) of - undefined -> - {Pid,Ref} = spawn_opt(fun() -> init(Me) end, - [link,monitor,{message_queue_data,off_heap}]), - receive - {'DOWN',Ref,process,Pid,Reason} -> - {error,Reason}; - {Pid,started} -> - erlang:demonitor(Ref), - {ok,Config} - end; - _ -> - {error,{handler_process_name_already_exists,?MODULE}} - end. - -removing_handler(#{id:=?MODULE}) -> - case whereis(?MODULE) of - undefined -> - ok; - Pid -> - Ref = erlang:monitor(process,Pid), - unlink(Pid), - Pid ! stop, - receive {'DOWN',Ref,process,Pid,_} -> - ok - end - end. - -log(#{meta:=#{error_logger:=#{tag:=info_report,type:=Type}}},_Config) - when Type=/=std_info -> - %% Skip info reports that are not 'std_info' (ref simple logger in - %% error_logger) - ok; -log(#{msg:=_,meta:=#{time:=_}}=Log,_Config) -> - _ = case whereis(?MODULE) of - undefined -> - %% Is the node on the way down? Real emergency? - %% Log directly from client just to get it out - do_log( - #{level=>error, - msg=>{report,{error,simple_handler_process_dead}}, - meta=>#{time=>erlang:system_time(microsecond)}}), - do_log(Log); - _ -> - ?MODULE ! {log,Log} - end, - ok; -log(_,_) -> - %% Unexpected log. - %% We don't want to crash the simple logger, so ignore this. - ok. - -%%%----------------------------------------------------------------- -%%% Process -init(Starter) -> - register(?MODULE,self()), - Starter ! {self(),started}, - loop(#{buffer_size=>10,dropped=>0,buffer=>[]}). - -loop(Buffer) -> - receive - stop -> - %% We replay the logger messages of there is - %% a default handler when the simple handler - %% is removed. - case logger:get_handler_config(default) of - {ok, _} -> - replay_buffer(Buffer); - _ -> - ok - end; - {log,#{msg:=_,meta:=#{time:=_}}=Log} -> - do_log(Log), - loop(update_buffer(Buffer,Log)); - _ -> - %% Unexpected message - flush it! - loop(Buffer) - end. - -update_buffer(#{buffer_size:=0,dropped:=D}=Buffer,_Log) -> - Buffer#{dropped=>D+1}; -update_buffer(#{buffer_size:=S,buffer:=B}=Buffer,Log) -> - Buffer#{buffer_size=>S-1,buffer=>[Log|B]}. - -replay_buffer(#{ dropped := D, buffer := Buffer }) -> - lists:foreach( - fun F(#{msg := {Tag, Msg}} = L) when Tag =:= string; Tag =:= report -> - F(L#{ msg := Msg }); - F(#{ level := Level, msg := Msg, meta := MD}) -> - logger:log(Level, Msg, MD) - end, lists:reverse(Buffer, drop_msg(D))). - -drop_msg(0) -> - []; -drop_msg(N) -> - [#{level=>info, - msg=>{"Simple handler buffer full, dropped ~w messages",[N]}, - meta=>#{time=>erlang:system_time(microsecond)}}]. - -%%%----------------------------------------------------------------- -%%% Internal - -%% Can't do io_lib:format - -do_log(#{msg:={report,Report}, - meta:=#{time:=T,error_logger:=#{type:=Type}}}) -> - display_date(T), - display_report(Type,Report); -do_log(#{msg:=Msg,meta:=#{time:=T}}) -> - display_date(T), - display(Msg). - -display_date(Timestamp) when is_integer(Timestamp) -> - Micro = Timestamp rem 1000000, - Sec = Timestamp div 1000000, - {{Y,Mo,D},{H,Mi,S}} = erlang:universaltime_to_localtime( - erlang:posixtime_to_universaltime(Sec)), - erlang:display_string( - integer_to_list(Y) ++ "-" ++ - pad(Mo,2) ++ "-" ++ - pad(D,2) ++ " " ++ - pad(H,2) ++ ":" ++ - pad(Mi,2) ++ ":" ++ - pad(S,2) ++ "." ++ - pad(Micro,6) ++ " "). - -pad(Int,Size) when is_integer(Int) -> - pad(integer_to_list(Int),Size); -pad(Str,Size) when length(Str)==Size -> - Str; -pad(Str,Size) -> - pad([$0|Str],Size). - -display({string,Chardata}) -> - try unicode:characters_to_list(Chardata) of - String -> erlang:display_string(String), erlang:display_string("\n") - catch _:_ -> erlang:display(Chardata) - end; -display({report,Report}) when is_map(Report) -> - display_report(maps:to_list(Report)); -display({report,Report}) -> - display_report(Report); -display({F, A}) when is_list(F), is_list(A) -> - erlang:display_string(F ++ "\n"), - [begin - erlang:display_string("\t"), - erlang:display(Arg) - end || Arg <- A], - ok. - -display_report(Atom, A) when is_atom(Atom) -> - %% The widest atom seems to be 'supervisor_report' at 17. - ColumnWidth = 20, - AtomString = atom_to_list(Atom), - AtomLength = length(AtomString), - Padding = lists:duplicate(ColumnWidth - AtomLength, $\s), - erlang:display_string(AtomString ++ Padding), - display_report(A); -display_report(F, A) -> - erlang:display({F, A}). - -display_report([A, []]) -> - %% Special case for crash reports when process has no links - display_report(A); -display_report(A = [_|_]) -> - case lists:all(fun({Key,_Value}) -> is_atom(Key); (_) -> false end, A) of - true -> - erlang:display_string("\n"), - lists:foreach( - fun({Key, Value}) -> - erlang:display_string( - " " ++ - atom_to_list(Key) ++ - ": "), - erlang:display(Value) - end, A); - false -> - erlang:display(A) - end; -display_report(A) -> - erlang:display(A). diff --git a/lib/kernel/src/logger_simple_h.erl b/lib/kernel/src/logger_simple_h.erl new file mode 100644 index 0000000000..19fb3b54ba --- /dev/null +++ b/lib/kernel/src/logger_simple_h.erl @@ -0,0 +1,212 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2017. 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. +%% +%% %CopyrightEnd% +%% +-module(logger_simple_h). + +-export([adding_handler/1, removing_handler/1, log/2]). + +%% This module implements a simple handler for logger. It is the +%% default used during system start. + +%%%----------------------------------------------------------------- +%%% Logger callback + +adding_handler(#{id:=simple}=Config) -> + Me = self(), + case whereis(?MODULE) of + undefined -> + {Pid,Ref} = spawn_opt(fun() -> init(Me) end, + [link,monitor,{message_queue_data,off_heap}]), + receive + {'DOWN',Ref,process,Pid,Reason} -> + {error,Reason}; + {Pid,started} -> + erlang:demonitor(Ref), + {ok,Config} + end; + _ -> + {error,{handler_process_name_already_exists,?MODULE}} + end. + +removing_handler(#{id:=simple}) -> + case whereis(?MODULE) of + undefined -> + ok; + Pid -> + Ref = erlang:monitor(process,Pid), + unlink(Pid), + Pid ! stop, + receive {'DOWN',Ref,process,Pid,_} -> + ok + end + end. + +log(#{meta:=#{error_logger:=#{tag:=info_report,type:=Type}}},_Config) + when Type=/=std_info -> + %% Skip info reports that are not 'std_info' (ref simple logger in + %% error_logger) + ok; +log(#{msg:=_,meta:=#{time:=_}}=Log,_Config) -> + _ = case whereis(?MODULE) of + undefined -> + %% Is the node on the way down? Real emergency? + %% Log directly from client just to get it out + do_log( + #{level=>error, + msg=>{report,{error,simple_handler_process_dead}}, + meta=>#{time=>erlang:system_time(microsecond)}}), + do_log(Log); + _ -> + ?MODULE ! {log,Log} + end, + ok; +log(_,_) -> + %% Unexpected log. + %% We don't want to crash the simple logger, so ignore this. + ok. + +%%%----------------------------------------------------------------- +%%% Process +init(Starter) -> + register(?MODULE,self()), + Starter ! {self(),started}, + loop(#{buffer_size=>10,dropped=>0,buffer=>[]}). + +loop(Buffer) -> + receive + stop -> + %% We replay the logger messages of there is + %% a default handler when the simple handler + %% is removed. + case logger:get_handler_config(default) of + {ok, _} -> + replay_buffer(Buffer); + _ -> + ok + end; + {log,#{msg:=_,meta:=#{time:=_}}=Log} -> + do_log(Log), + loop(update_buffer(Buffer,Log)); + _ -> + %% Unexpected message - flush it! + loop(Buffer) + end. + +update_buffer(#{buffer_size:=0,dropped:=D}=Buffer,_Log) -> + Buffer#{dropped=>D+1}; +update_buffer(#{buffer_size:=S,buffer:=B}=Buffer,Log) -> + Buffer#{buffer_size=>S-1,buffer=>[Log|B]}. + +replay_buffer(#{ dropped := D, buffer := Buffer }) -> + lists:foreach( + fun F(#{msg := {Tag, Msg}} = L) when Tag =:= string; Tag =:= report -> + F(L#{ msg := Msg }); + F(#{ level := Level, msg := Msg, meta := MD}) -> + logger:log(Level, Msg, MD) + end, lists:reverse(Buffer, drop_msg(D))). + +drop_msg(0) -> + []; +drop_msg(N) -> + [#{level=>info, + msg=>{"Simple handler buffer full, dropped ~w messages",[N]}, + meta=>#{time=>erlang:system_time(microsecond)}}]. + +%%%----------------------------------------------------------------- +%%% Internal + +%% Can't do io_lib:format + +do_log(#{msg:={report,Report}, + meta:=#{time:=T,error_logger:=#{type:=Type}}}) -> + display_date(T), + display_report(Type,Report); +do_log(#{msg:=Msg,meta:=#{time:=T}}) -> + display_date(T), + display(Msg). + +display_date(Timestamp) when is_integer(Timestamp) -> + Micro = Timestamp rem 1000000, + Sec = Timestamp div 1000000, + {{Y,Mo,D},{H,Mi,S}} = erlang:universaltime_to_localtime( + erlang:posixtime_to_universaltime(Sec)), + erlang:display_string( + integer_to_list(Y) ++ "-" ++ + pad(Mo,2) ++ "-" ++ + pad(D,2) ++ " " ++ + pad(H,2) ++ ":" ++ + pad(Mi,2) ++ ":" ++ + pad(S,2) ++ "." ++ + pad(Micro,6) ++ " "). + +pad(Int,Size) when is_integer(Int) -> + pad(integer_to_list(Int),Size); +pad(Str,Size) when length(Str)==Size -> + Str; +pad(Str,Size) -> + pad([$0|Str],Size). + +display({string,Chardata}) -> + try unicode:characters_to_list(Chardata) of + String -> erlang:display_string(String), erlang:display_string("\n") + catch _:_ -> erlang:display(Chardata) + end; +display({report,Report}) when is_map(Report) -> + display_report(maps:to_list(Report)); +display({report,Report}) -> + display_report(Report); +display({F, A}) when is_list(F), is_list(A) -> + erlang:display_string(F ++ "\n"), + [begin + erlang:display_string("\t"), + erlang:display(Arg) + end || Arg <- A], + ok. + +display_report(Atom, A) when is_atom(Atom) -> + %% The widest atom seems to be 'supervisor_report' at 17. + ColumnWidth = 20, + AtomString = atom_to_list(Atom), + AtomLength = length(AtomString), + Padding = lists:duplicate(ColumnWidth - AtomLength, $\s), + erlang:display_string(AtomString ++ Padding), + display_report(A); +display_report(F, A) -> + erlang:display({F, A}). + +display_report([A, []]) -> + %% Special case for crash reports when process has no links + display_report(A); +display_report(A = [_|_]) -> + case lists:all(fun({Key,_Value}) -> is_atom(Key); (_) -> false end, A) of + true -> + erlang:display_string("\n"), + lists:foreach( + fun({Key, Value}) -> + erlang:display_string( + " " ++ + atom_to_list(Key) ++ + ": "), + erlang:display(Value) + end, A); + false -> + erlang:display(A) + end; +display_report(A) -> + erlang:display(A). diff --git a/lib/kernel/test/Makefile b/lib/kernel/test/Makefile index 2f637ca9de..2ad1e3107c 100644 --- a/lib/kernel/test/Makefile +++ b/lib/kernel/test/Makefile @@ -77,7 +77,7 @@ MODULES= \ logger_filters_SUITE \ logger_formatter_SUITE \ logger_legacy_SUITE \ - logger_simple_SUITE \ + logger_simple_h_SUITE \ logger_std_h_SUITE \ logger_test_lib \ os_SUITE \ diff --git a/lib/kernel/test/logger.cover b/lib/kernel/test/logger.cover index b30bcfe920..960bc0abff 100644 --- a/lib/kernel/test/logger.cover +++ b/lib/kernel/test/logger.cover @@ -8,7 +8,7 @@ logger_filters, logger_formatter, logger_server, - logger_simple, + logger_simple_h, logger_std_h, logger_sup]}. diff --git a/lib/kernel/test/logger.spec b/lib/kernel/test/logger.spec index cd76a754a4..1ab90b3e93 100644 --- a/lib/kernel/test/logger.spec +++ b/lib/kernel/test/logger.spec @@ -7,5 +7,5 @@ logger_filters_SUITE, logger_formatter_SUITE, logger_legacy_SUITE, - logger_simple_SUITE, + logger_simple_h_SUITE, logger_std_h_SUITE]}. diff --git a/lib/kernel/test/logger_env_var_SUITE.erl b/lib/kernel/test/logger_env_var_SUITE.erl index a808a31f17..601d331fb0 100644 --- a/lib/kernel/test/logger_env_var_SUITE.erl +++ b/lib/kernel/test/logger_env_var_SUITE.erl @@ -85,7 +85,7 @@ default(Config) -> {domain,{_,{log,super,[beam,erlang,otp,sasl]}}} = lists:keyfind(domain,1,StdFilters), true = lists:keymember(stop_progress,1,StdFilters), - false = lists:keymember(logger_simple,1,Hs), + false = lists:keymember(simple,1,Hs), false = lists:keymember(sasl,1,Hs), ok. @@ -98,7 +98,7 @@ default_sasl_compatible(Config) -> {domain,{_,{log,super,[beam,erlang,otp]}}} = lists:keyfind(domain,1,StdFilters), false = lists:keymember(stop_progress,1,StdFilters), - false = lists:keymember(logger_simple,1,Hs), + false = lists:keymember(simple,1,Hs), true = lists:keymember(sasl,1,Hs), ok. @@ -110,7 +110,7 @@ error_logger_tty(Config) -> {domain,{_,{log,super,[beam,erlang,otp,sasl]}}} = lists:keyfind(domain,1,StdFilters), true = lists:keymember(stop_progress,1,StdFilters), - false = lists:keymember(logger_simple,1,Hs), + false = lists:keymember(simple,1,Hs), false = lists:keymember(sasl,1,Hs), ok. @@ -124,7 +124,7 @@ error_logger_tty_sasl_compatible(Config) -> {domain,{_,{log,super,[beam,erlang,otp]}}} = lists:keyfind(domain,1,StdFilters), false = lists:keymember(stop_progress,1,StdFilters), - false = lists:keymember(logger_simple,1,Hs), + false = lists:keymember(simple,1,Hs), true = lists:keymember(sasl,1,Hs), ok. @@ -134,7 +134,7 @@ error_logger_false(Config) -> [{error_logger,false}, {logger_level,notice}]), false = lists:keymember(?STANDARD_HANDLER,1,Hs), - {logger_simple,logger_simple,SimpleC} = lists:keyfind(logger_simple,1,Hs), + {simple,logger_simple_h,SimpleC} = lists:keyfind(simple,1,Hs), info = maps:get(level,SimpleC), notice = maps:get(level,L), SimpleFilters = maps:get(filters,SimpleC), @@ -151,7 +151,7 @@ error_logger_false_progress(Config) -> {logger_level,notice}, {logger_progress_reports,log}]), false = lists:keymember(?STANDARD_HANDLER,1,Hs), - {logger_simple,logger_simple,SimpleC} = lists:keyfind(logger_simple,1,Hs), + {simple,logger_simple_h,SimpleC} = lists:keyfind(simple,1,Hs), info = maps:get(level,SimpleC), notice = maps:get(level,L), SimpleFilters = maps:get(filters,SimpleC), @@ -168,7 +168,7 @@ error_logger_false_sasl_compatible(Config) -> {logger_level,notice}, {logger_sasl_compatible,true}]), false = lists:keymember(?STANDARD_HANDLER,1,Hs), - {logger_simple,logger_simple,SimpleC} = lists:keyfind(logger_simple,1,Hs), + {simple,logger_simple_h,SimpleC} = lists:keyfind(simple,1,Hs), info = maps:get(level,SimpleC), notice = maps:get(level,L), SimpleFilters = maps:get(filters,SimpleC), @@ -182,7 +182,7 @@ error_logger_silent(Config) -> {ok,#{handlers:=Hs},_Node} = setup(Config, [{error_logger,silent}]), false = lists:keymember(?STANDARD_HANDLER,1,Hs), - false = lists:keymember(logger_simple,1,Hs), + false = lists:keymember(simple,1,Hs), false = lists:keymember(sasl,1,Hs), ok. @@ -191,7 +191,7 @@ error_logger_silent_sasl_compatible(Config) -> [{error_logger,silent}, {logger_sasl_compatible,true}]), false = lists:keymember(?STANDARD_HANDLER,1,Hs), - false = lists:keymember(logger_simple,1,Hs), + false = lists:keymember(simple,1,Hs), true = lists:keymember(sasl,1,Hs), ok. @@ -223,7 +223,7 @@ logger_file(Config) -> {domain,{_,{log,super,[beam,erlang,otp,sasl]}}} = lists:keyfind(domain,1,StdFilters), true = lists:keymember(stop_progress,1,StdFilters), - false = lists:keymember(logger_simple,1,Hs), + false = lists:keymember(simple,1,Hs), false = lists:keymember(sasl,1,Hs), ok. @@ -246,7 +246,7 @@ logger_file_sasl_compatible(Config) -> {domain,{_,{log,super,[beam,erlang,otp]}}} = lists:keyfind(domain,1,StdFilters), false = lists:keymember(stop_progress,1,StdFilters), - false = lists:keymember(logger_simple,1,Hs), + false = lists:keymember(simple,1,Hs), true = lists:keymember(sasl,1,Hs), ok. @@ -269,7 +269,7 @@ logger_file_log_progress(Config) -> {domain,{_,{log,super,[beam,erlang,otp,sasl]}}} = lists:keyfind(domain,1,StdFilters), false = lists:keymember(stop_progress,1,StdFilters), - false = lists:keymember(logger_simple,1,Hs), + false = lists:keymember(simple,1,Hs), false = lists:keymember(sasl,1,Hs), ok. @@ -289,7 +289,7 @@ logger_file_no_filter(Config) -> {?STANDARD_HANDLER,logger_std_h,StdC} = lists:keyfind(?STANDARD_HANDLER,1,Hs), info = maps:get(level,StdC), [] = maps:get(filters,StdC), - false = lists:keymember(logger_simple,1,Hs), + false = lists:keymember(simple,1,Hs), false = lists:keymember(sasl,1,Hs), ok. @@ -310,7 +310,7 @@ logger_file_no_filter_level(Config) -> {?STANDARD_HANDLER,logger_std_h,StdC} = lists:keyfind(?STANDARD_HANDLER,1,Hs), error = maps:get(level,StdC), [] = maps:get(filters,StdC), - false = lists:keymember(logger_simple,1,Hs), + false = lists:keymember(simple,1,Hs), false = lists:keymember(sasl,1,Hs), ok. @@ -331,7 +331,7 @@ logger_file_formatter(Config) -> {?STANDARD_HANDLER,logger_std_h,StdC} = lists:keyfind(?STANDARD_HANDLER,1,Hs), info = maps:get(level,StdC), [] = maps:get(filters,StdC), - false = lists:keymember(logger_simple,1,Hs), + false = lists:keymember(simple,1,Hs), false = lists:keymember(sasl,1,Hs), ok. @@ -356,7 +356,7 @@ logger_filters(Config) -> {domain,{_,{log,super,[beam,erlang,otp,sasl]}}} = lists:keyfind(domain,1,StdFilters), false = lists:keymember(stop_progress,1,StdFilters), - false = lists:keymember(logger_simple,1,Hs), + false = lists:keymember(simple,1,Hs), false = lists:keymember(sasl,1,Hs), LoggerFilters = maps:get(filters,Logger), true = lists:keymember(stop_progress,1,LoggerFilters), @@ -382,8 +382,8 @@ logger_filters_stop(Config) -> {?STANDARD_HANDLER,logger_std_h,StdC} = lists:keyfind(?STANDARD_HANDLER,1,Hs), info = maps:get(level,StdC), [] = maps:get(filters,StdC), - false = lists:keymember(logger_simple,1,Hs), - false = lists:keymember(sasl_h,1,Hs), + false = lists:keymember(simple,1,Hs), + false = lists:keymember(sasl,1,Hs), LoggerFilters = maps:get(filters,Logger), true = lists:keymember(log_error,1,LoggerFilters), @@ -409,7 +409,7 @@ logger_module_level(Config) -> {domain,{_,{log,super,[beam,erlang,otp,sasl]}}} = lists:keyfind(domain,1,StdFilters), false = lists:keymember(stop_progress,1,StdFilters), - false = lists:keymember(logger_simple,1,Hs), + false = lists:keymember(simple,1,Hs), false = lists:keymember(sasl,1,Hs), [{supervisor,error}] = ModuleLevels, ok. @@ -431,7 +431,7 @@ logger_disk_log(Config) -> {domain,{_,{log,super,[beam,erlang,otp,sasl]}}} = lists:keyfind(domain,1,StdFilters), true = lists:keymember(stop_progress,1,StdFilters), - false = lists:keymember(logger_simple,1,Hs), + false = lists:keymember(simple,1,Hs), false = lists:keymember(sasl,1,Hs), ok. @@ -452,7 +452,7 @@ logger_disk_log_formatter(Config) -> {?STANDARD_HANDLER,logger_disk_log_h,StdC} = lists:keyfind(?STANDARD_HANDLER,1,Hs), info = maps:get(level,StdC), [] = maps:get(filters,StdC), - false = lists:keymember(logger_simple,1,Hs), + false = lists:keymember(simple,1,Hs), false = lists:keymember(sasl,1,Hs), ok. @@ -461,7 +461,7 @@ logger_undefined(Config) -> {ok,#{handlers:=Hs,logger:=L},_Node} = setup(Config,[{logger,[{handler,?STANDARD_HANDLER,undefined}]}]), false = lists:keymember(?STANDARD_HANDLER,1,Hs), - {logger_simple,logger_simple,SimpleC} = lists:keyfind(logger_simple,1,Hs), + {simple,logger_simple_h,SimpleC} = lists:keyfind(simple,1,Hs), info = maps:get(level,SimpleC), info = maps:get(level,L), SimpleFilters = maps:get(filters,SimpleC), diff --git a/lib/kernel/test/logger_simple_SUITE.erl b/lib/kernel/test/logger_simple_SUITE.erl deleted file mode 100644 index d7f9fa21cf..0000000000 --- a/lib/kernel/test/logger_simple_SUITE.erl +++ /dev/null @@ -1,210 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 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. -%% 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. -%% -%% %CopyrightEnd% -%% --module(logger_simple_SUITE). - --compile(export_all). - --include_lib("common_test/include/ct.hrl"). --include_lib("kernel/include/logger.hrl"). --include_lib("kernel/src/logger_internal.hrl"). - --import(logger_test_lib, [setup/2, log/3, sync_and_read/3]). - --define(check_no_log,[] = test_server:messages_get()). --define(check(Expected), - receive {log,Expected} -> - [] = test_server:messages_get() - after 1000 -> - ct:fail({report_not_received, - {line,?LINE}, - {expected,Expected}, - {got,test_server:messages_get()}}) - end). - --define(str,"Log from "++atom_to_list(?FUNCTION_NAME)++ - ":"++integer_to_list(?LINE)). --define(map_rep,#{function=>?FUNCTION_NAME, line=>?LINE}). --define(keyval_rep,[{function,?FUNCTION_NAME}, {line,?LINE}]). - -suite() -> - [{timetrap,{seconds,30}}, - {ct_hooks, [logger_test_lib]}]. - -init_per_suite(Config) -> - #{handlers:=Hs0} = logger:i(), - Hs = lists:keydelete(cth_log_redirect,1,Hs0), - [ok = logger:remove_handler(Id) || {Id,_,_} <- Hs], - Env = [{App,Key,application:get_env(App,Key)} || - {App,Key} <- [{kernel,logger_level}]], - [{env,Env},{logger,Hs}|Config]. - -end_per_suite(Config) -> - [application:set_env(App,Key,Val) || {App,Key,Val} <- ?config(env,Config)], - Hs = ?config(logger,Config), - [ok = logger:add_handler(Id,Mod,C) || {Id,Mod,C} <- Hs], - ok. - -init_per_group(_Group, Config) -> - Config. - -end_per_group(_Group, _Config) -> - ok. - -init_per_testcase(_TestCase, Config) -> - Config. - -end_per_testcase(Case, Config) -> - try apply(?MODULE,Case,[cleanup,Config]) - catch error:undef -> ok - end, - ok. - -groups() -> - []. - -all() -> - [start_stop, - replace_default, - replace_file, - replace_disk_log - ]. - -start_stop(_Config) -> - undefined = whereis(logger_simple), - register(logger_simple,self()), - {error,_} = logger:add_handler(logger_simple, - logger_simple, - #{filter_default=>log}), - unregister(logger_simple), - ok = logger:add_handler(logger_simple,logger_simple,#{filter_default=>log}), - Pid = whereis(logger_simple), - true = is_pid(Pid), - ok = logger:remove_handler(logger_simple), - false = is_pid(whereis(logger_simple)), - ok. -start_stop(cleanup,_Config) -> - logger:remove_handler(logger_simple). - -%% This testcase just tests that it does not crash, the default handler prints -%% to stdout which we cannot read from in a detached slave. -replace_default(Config) -> - - {ok, _, Node} = logger_test_lib:setup(Config, [{logger, [{handler, default, undefined}]}]), - log(Node, emergency, [M1=?str]), - log(Node, alert, [M2=?str,[]]), - log(Node, error, [M3=?map_rep]), - log(Node, info, [M4=?keyval_rep]), - log(Node, info, [M41=?keyval_rep++[not_key_val]]), - rpc:call(Node, error_logger, error_report, [some_type,M5=?map_rep]), - rpc:call(Node, error_logger, warning_report, ["some_type",M6=?map_rep]), - log(Node, critical, [M7=?str,[A7=?keyval_rep]]), - log(Node, notice, [M8=["fake",string,"line:",?LINE]]), - - Env = rpc:call(Node, application, get_env, [kernel, logger, []]), - ok = rpc:call(Node, logger, add_handlers, [Env]), - - ok. - -replace_file(Config) -> - - {ok, _, Node} = logger_test_lib:setup(Config, [{logger, [{handler, default, undefined}]}]), - log(Node, emergency, [M1=?str]), - log(Node, alert, [M2=?str,[]]), - log(Node, error, [M3=?map_rep]), - log(Node, info, [M4=?keyval_rep]), - log(Node, info, [M41=?keyval_rep++[not_key_val]]), - log(Node, critical, [M7=?str,[A7=?keyval_rep]]), - log(Node, notice, [M8=["fake",string,"line:",?LINE]]), - - File = filename:join(proplists:get_value(priv_dir,Config), - atom_to_list(?FUNCTION_NAME)++".log"), - - ok = rpc:call(Node, logger, add_handlers, - [[{handler, default, logger_std_h, - #{ logger_std_h => #{ type => {file, File} }, - formatter => {?DEFAULT_FORMATTER,?DEFAULT_FORMAT_CONFIG}}}]]), - - {ok,Bin} = sync_and_read(Node, file, File), - Lines = [unicode:characters_to_list(L) || - L <- binary:split(Bin,<<"\n">>,[global,trim])], - ["=EMERGENCY REPORT===="++_, - M1, - "=ALERT REPORT===="++_, - M2, - "=ERROR REPORT===="++_, - _, - _, - "=INFO REPORT===="++_, - _, - _, - "=INFO REPORT===="++_, - _, - _, - _, - "=CRITICAL REPORT===="++_, - _, - _, - "=NOTICE REPORT===="++_, - _ - ] = Lines, - ok. - -replace_disk_log(Config) -> - - {ok, _, Node} = logger_test_lib:setup(Config, [{logger, [{handler, default, undefined}]}]), - log(Node, emergency, [M1=?str]), - log(Node, alert, [M2=?str,[]]), - log(Node, error, [M3=?map_rep]), - log(Node, info, [M4=?keyval_rep]), - log(Node, info, [M41=?keyval_rep++[not_key_val]]), - log(Node, critical, [M7=?str,[A7=?keyval_rep]]), - log(Node, notice, [M8=["fake",string,"line:",?LINE]]), - - File = filename:join(proplists:get_value(priv_dir,Config), - atom_to_list(?FUNCTION_NAME)++".log"), - - ok = rpc:call(Node, logger, add_handlers, - [[{handler, default, logger_disk_log_h, - #{ disk_log_opts => #{ file => File }, - formatter => {?DEFAULT_FORMATTER,?DEFAULT_FORMAT_CONFIG}}}]]), - {ok,Bin} = sync_and_read(Node, disk_log, File), - Lines = [unicode:characters_to_list(L) || - L <- binary:split(Bin,<<"\n">>,[global,trim])], - ["=EMERGENCY REPORT===="++_, - M1, - "=ALERT REPORT===="++_, - M2, - "=ERROR REPORT===="++_, - _, - _, - "=INFO REPORT===="++_, - _, - _, - "=INFO REPORT===="++_, - _, - _, - _, - "=CRITICAL REPORT===="++_, - _, - _, - "=NOTICE REPORT===="++_, - _ - ] = Lines, - ok. diff --git a/lib/kernel/test/logger_simple_h_SUITE.erl b/lib/kernel/test/logger_simple_h_SUITE.erl new file mode 100644 index 0000000000..271a2126de --- /dev/null +++ b/lib/kernel/test/logger_simple_h_SUITE.erl @@ -0,0 +1,210 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 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. +%% 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. +%% +%% %CopyrightEnd% +%% +-module(logger_simple_h_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("kernel/include/logger.hrl"). +-include_lib("kernel/src/logger_internal.hrl"). + +-import(logger_test_lib, [setup/2, log/3, sync_and_read/3]). + +-define(check_no_log,[] = test_server:messages_get()). +-define(check(Expected), + receive {log,Expected} -> + [] = test_server:messages_get() + after 1000 -> + ct:fail({report_not_received, + {line,?LINE}, + {expected,Expected}, + {got,test_server:messages_get()}}) + end). + +-define(str,"Log from "++atom_to_list(?FUNCTION_NAME)++ + ":"++integer_to_list(?LINE)). +-define(map_rep,#{function=>?FUNCTION_NAME, line=>?LINE}). +-define(keyval_rep,[{function,?FUNCTION_NAME}, {line,?LINE}]). + +suite() -> + [{timetrap,{seconds,30}}, + {ct_hooks, [logger_test_lib]}]. + +init_per_suite(Config) -> + #{handlers:=Hs0} = logger:i(), + Hs = lists:keydelete(cth_log_redirect,1,Hs0), + [ok = logger:remove_handler(Id) || {Id,_,_} <- Hs], + Env = [{App,Key,application:get_env(App,Key)} || + {App,Key} <- [{kernel,logger_level}]], + [{env,Env},{logger,Hs}|Config]. + +end_per_suite(Config) -> + [application:set_env(App,Key,Val) || {App,Key,Val} <- ?config(env,Config)], + Hs = ?config(logger,Config), + [ok = logger:add_handler(Id,Mod,C) || {Id,Mod,C} <- Hs], + ok. + +init_per_group(_Group, Config) -> + Config. + +end_per_group(_Group, _Config) -> + ok. + +init_per_testcase(_TestCase, Config) -> + Config. + +end_per_testcase(Case, Config) -> + try apply(?MODULE,Case,[cleanup,Config]) + catch error:undef -> ok + end, + ok. + +groups() -> + []. + +all() -> + [start_stop, + replace_default, + replace_file, + replace_disk_log + ]. + +start_stop(_Config) -> + undefined = whereis(logger_simple_h), + register(logger_simple_h,self()), + {error,_} = logger:add_handler(simple, + logger_simple_h, + #{filter_default=>log}), + unregister(logger_simple_h), + ok = logger:add_handler(simple,logger_simple_h,#{filter_default=>log}), + Pid = whereis(logger_simple_h), + true = is_pid(Pid), + ok = logger:remove_handler(simple), + false = is_pid(whereis(logger_simple_h)), + ok. +start_stop(cleanup,_Config) -> + logger:remove_handler(simple). + +%% This testcase just tests that it does not crash, the default handler prints +%% to stdout which we cannot read from in a detached slave. +replace_default(Config) -> + + {ok, _, Node} = logger_test_lib:setup(Config, [{logger, [{handler, default, undefined}]}]), + log(Node, emergency, [M1=?str]), + log(Node, alert, [M2=?str,[]]), + log(Node, error, [M3=?map_rep]), + log(Node, info, [M4=?keyval_rep]), + log(Node, info, [M41=?keyval_rep++[not_key_val]]), + rpc:call(Node, error_logger, error_report, [some_type,M5=?map_rep]), + rpc:call(Node, error_logger, warning_report, ["some_type",M6=?map_rep]), + log(Node, critical, [M7=?str,[A7=?keyval_rep]]), + log(Node, notice, [M8=["fake",string,"line:",?LINE]]), + + Env = rpc:call(Node, application, get_env, [kernel, logger, []]), + ok = rpc:call(Node, logger, add_handlers, [Env]), + + ok. + +replace_file(Config) -> + + {ok, _, Node} = logger_test_lib:setup(Config, [{logger, [{handler, default, undefined}]}]), + log(Node, emergency, [M1=?str]), + log(Node, alert, [M2=?str,[]]), + log(Node, error, [M3=?map_rep]), + log(Node, info, [M4=?keyval_rep]), + log(Node, info, [M41=?keyval_rep++[not_key_val]]), + log(Node, critical, [M7=?str,[A7=?keyval_rep]]), + log(Node, notice, [M8=["fake",string,"line:",?LINE]]), + + File = filename:join(proplists:get_value(priv_dir,Config), + atom_to_list(?FUNCTION_NAME)++".log"), + + ok = rpc:call(Node, logger, add_handlers, + [[{handler, default, logger_std_h, + #{ logger_std_h => #{ type => {file, File} }, + formatter => {?DEFAULT_FORMATTER,?DEFAULT_FORMAT_CONFIG}}}]]), + + {ok,Bin} = sync_and_read(Node, file, File), + Lines = [unicode:characters_to_list(L) || + L <- binary:split(Bin,<<"\n">>,[global,trim])], + ["=EMERGENCY REPORT===="++_, + M1, + "=ALERT REPORT===="++_, + M2, + "=ERROR REPORT===="++_, + _, + _, + "=INFO REPORT===="++_, + _, + _, + "=INFO REPORT===="++_, + _, + _, + _, + "=CRITICAL REPORT===="++_, + _, + _, + "=NOTICE REPORT===="++_, + _ + ] = Lines, + ok. + +replace_disk_log(Config) -> + + {ok, _, Node} = logger_test_lib:setup(Config, [{logger, [{handler, default, undefined}]}]), + log(Node, emergency, [M1=?str]), + log(Node, alert, [M2=?str,[]]), + log(Node, error, [M3=?map_rep]), + log(Node, info, [M4=?keyval_rep]), + log(Node, info, [M41=?keyval_rep++[not_key_val]]), + log(Node, critical, [M7=?str,[A7=?keyval_rep]]), + log(Node, notice, [M8=["fake",string,"line:",?LINE]]), + + File = filename:join(proplists:get_value(priv_dir,Config), + atom_to_list(?FUNCTION_NAME)++".log"), + + ok = rpc:call(Node, logger, add_handlers, + [[{handler, default, logger_disk_log_h, + #{ disk_log_opts => #{ file => File }, + formatter => {?DEFAULT_FORMATTER,?DEFAULT_FORMAT_CONFIG}}}]]), + {ok,Bin} = sync_and_read(Node, disk_log, File), + Lines = [unicode:characters_to_list(L) || + L <- binary:split(Bin,<<"\n">>,[global,trim])], + ["=EMERGENCY REPORT===="++_, + M1, + "=ALERT REPORT===="++_, + M2, + "=ERROR REPORT===="++_, + _, + _, + "=INFO REPORT===="++_, + _, + _, + "=INFO REPORT===="++_, + _, + _, + _, + "=CRITICAL REPORT===="++_, + _, + _, + "=NOTICE REPORT===="++_, + _ + ] = Lines, + ok. diff --git a/lib/sasl/src/systools_make.erl b/lib/sasl/src/systools_make.erl index f4b1b54fd1..6916107623 100644 --- a/lib/sasl/src/systools_make.erl +++ b/lib/sasl/src/systools_make.erl @@ -1551,7 +1551,7 @@ mandatory_modules() -> logger_server, logger_backend, logger_config, - logger_simple, + logger_simple_h, lists, proc_lib, supervisor -- cgit v1.2.3 From 72f1ce276401e0b8de9c0c527cbc324da0186939 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Wed, 23 May 2018 12:34:30 +0200 Subject: Change type name logger:log() to logger:log_event() --- lib/kernel/doc/src/logger.xml | 18 +++++------ lib/kernel/doc/src/logger_chapter.xml | 26 ++++++++-------- lib/kernel/src/error_logger.erl | 2 +- lib/kernel/src/logger.erl | 21 +++++++------ lib/kernel/src/logger_backend.erl | 4 +-- lib/kernel/src/logger_disk_log_h.erl | 8 ++--- lib/kernel/src/logger_filters.erl | 50 +++++++++++++++--------------- lib/kernel/src/logger_formatter.erl | 4 +-- lib/kernel/src/logger_h_common.erl | 8 ++--- lib/kernel/src/logger_std_h.erl | 8 ++--- lib/kernel/test/logger_formatter_SUITE.erl | 2 +- 11 files changed, 76 insertions(+), 75 deletions(-) (limited to 'lib') diff --git a/lib/kernel/doc/src/logger.xml b/lib/kernel/doc/src/logger.xml index d6576db6f3..bb356c5b86 100644 --- a/lib/kernel/doc/src/logger.xml +++ b/lib/kernel/doc/src/logger.xml @@ -87,7 +87,7 @@ logger:error("error happened because: ~p",[Reason]). %% Without macro - +

@@ -446,7 +446,7 @@ Current logger configuration:

The return value of the fun specifies if a log event is to be discarded or forwarded to the handlers:

- log() + log_event()

The filter passed. The next logger filter, if any, is applied. If no more logger filters exist, the @@ -487,7 +487,7 @@ Current logger configuration:

The return value of the fun specifies if a log event is to be discarded or forwarded to the handler callback:

- log() + log_event()

The filter passed. The next handler filter, if any, is applied. If no more filters exist for this @@ -929,11 +929,11 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(),Meta)). - HModule:log(Log,Config) -> void() + HModule:log(LogEvent,Config) -> void() Log the given log event. - Log = - log() + LogEvent = + log_event() Config = config() @@ -979,11 +979,11 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(),Meta)). - FModule:format(Log,FConfig) -> FormattedLogEntry + FModule:format(LogEvent,FConfig) -> FormattedLogEntry Format the given log event. - Log = - log() + LogEvent = + log_event() FConfig = formatter_config() FormattedLogEntry = diff --git a/lib/kernel/doc/src/logger_chapter.xml b/lib/kernel/doc/src/logger_chapter.xml index dff9ee2892..3b4cafb010 100644 --- a/lib/kernel/doc/src/logger_chapter.xml +++ b/lib/kernel/doc/src/logger_chapter.xml @@ -252,7 +252,7 @@

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

-
log(Log, Config)
+
log(LogEvent, Config)

This function is called when a log event has passed through all global filters, and all handler filters attached to the handler @@ -320,7 +320,7 @@ module, FModule and its configuration, FConfig. FModule must export the following function, which can be called by the handler:

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

See the logger_formatter(3) manual for the full @@ -735,7 +735,7 @@ 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 + log(logger:log_event(),logger:config()) -> ok

It may also implement the following callbacks:

adding_handler(logger:config()) -> {ok,logger:config()} | {error,term()} @@ -763,8 +763,8 @@ changing_config(logger:config(),logger:config()) -> {ok,logger:config()} | {erro -module(myhandler). -export([log/2]). -log(Log,#{formatter:={FModule,FConfig}) -> - io:put_chars(FModule:format(Log,FConfig)). +log(LogEvent,#{formatter:={FModule,FConfig}) -> + io:put_chars(FModule:format(LogEvent,FConfig)).

A simple handler which prints to file could be implemented like @@ -782,8 +782,8 @@ removing_handler(#{myhandler_fd:=Fd}) -> _ = file:close(Fd), ok. -log(Log,#{myhandler_fd:=Fd,formatter:={FModule,FConfig}}) -> - io:put_chars(Fd,FModule:format(Log,FConfig)). +log(LogEvent,#{myhandler_fd:=Fd,formatter:={FModule,FConfig}}) -> + io:put_chars(Fd,FModule:format(LogEvent,FConfig)).

The above handlers do not have any overload @@ -810,8 +810,8 @@ adding_handler(Config) -> removing_handler(#{myhandler_pid:=Pid}) -> gen_server:stop(Pid). -log(Log,#{myhandler_pid:=Pid} = Config) -> - gen_server:cast(Pid,{log,Log,Config}). +log(LogEvent,#{myhandler_pid:=Pid} = Config) -> + gen_server:cast(Pid,{log,LogEvent,Config}). init(#{myhandler_file:=File}) -> {ok,Fd} = file:open(File,[append,{encoding,utf8}]), @@ -820,16 +820,16 @@ init(#{myhandler_file:=File}) -> handle_call(_,_,State) -> {reply,{error,bad_request},State}. -handle_cast({log,Log,Config},#{fd:=Fd} = State) -> - do_log(Fd,Log,Config), +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,Log,#{formatter:={FModule,FConfig}}) -> - String = FModule:format(Log,FConfig), +do_log(Fd,LogEvent,#{formatter:={FModule,FConfig}}) -> + String = FModule:format(LogEvent,FConfig), io:put_chars(Fd,String).

diff --git a/lib/kernel/src/error_logger.erl b/lib/kernel/src/error_logger.erl index 96f6536e61..b3957d0c7e 100644 --- a/lib/kernel/src/error_logger.erl +++ b/lib/kernel/src/error_logger.erl @@ -116,7 +116,7 @@ removing_handler(#{id:=?MODULE}) -> stop(), ok. --spec log(logger:log(),logger:config()) -> ok. +-spec log(logger:log_event(),logger:config()) -> ok. log(#{level:=Level,msg:=Msg,meta:=Meta},_Config) -> do_log(Level,Msg,Meta). diff --git a/lib/kernel/src/logger.erl b/lib/kernel/src/logger.erl index f35036aa04..12f8dd77cf 100644 --- a/lib/kernel/src/logger.erl +++ b/lib/kernel/src/logger.erl @@ -64,11 +64,11 @@ %%%----------------------------------------------------------------- %%% Types --type log() :: #{level:=level(), - msg:={io:format(),[term()]} | - {report,report()} | - {string,unicode:chardata()}, - meta:=metadata()}. +-type log_event() :: #{level:=level(), + msg:={io:format(),[term()]} | + {report,report()} | + {string,unicode:chardata()}, + meta:=metadata()}. -type level() :: emergency | alert | critical | error | warning | notice | info | debug. -type report() :: map() | [{atom(),term()}]. @@ -87,9 +87,10 @@ line := non_neg_integer()}. -type handler_id() :: atom(). -type filter_id() :: atom(). --type filter() :: {fun((log(),filter_arg()) -> filter_return()),filter_arg()}. +-type filter() :: {fun((log_event(),filter_arg()) -> + filter_return()),filter_arg()}. -type filter_arg() :: term(). --type filter_return() :: stop | ignore | log(). +-type filter_return() :: stop | ignore | log_event(). -type config() :: #{id => handler_id(), level => level(), filter_default => log | stop, @@ -101,9 +102,9 @@ -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, - formatter_config/0]). +-export_type([log_event/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,formatter_config/0]). %%%----------------------------------------------------------------- %%% API diff --git a/lib/kernel/src/logger_backend.erl b/lib/kernel/src/logger_backend.erl index d9f5aa6faf..b3cf7d67dd 100644 --- a/lib/kernel/src/logger_backend.erl +++ b/lib/kernel/src/logger_backend.erl @@ -58,7 +58,7 @@ call_handlers(#{level:=Level}=Log,[Id|Handlers],Tid) -> debug, [{logger,removed_failing_handler}, {handler,{Id,Module}}, - {log,Log1}, + {log_event,Log1}, {config,Config1}, {reason,{C,R,filter_stacktrace(S)}}]); {error,{not_found,_}} -> @@ -122,7 +122,7 @@ handle_filter_failed({Id,_}=Filter,Owner,Log,Reason) -> [{logger,removed_failing_filter}, {filter,Filter}, {owner,Owner}, - {log,Log}, + {log_event,Log}, {reason,Reason}]); _ -> ok diff --git a/lib/kernel/src/logger_disk_log_h.erl b/lib/kernel/src/logger_disk_log_h.erl index 37a147e3dc..773aa75bc6 100644 --- a/lib/kernel/src/logger_disk_log_h.erl +++ b/lib/kernel/src/logger_disk_log_h.erl @@ -235,15 +235,15 @@ swap_buffer(Name,Buffer) -> %%%----------------------------------------------------------------- %%% Log a string or report --spec log(Log, Config) -> ok | dropped when - Log :: logger:log(), +-spec log(LogEvent, Config) -> ok | dropped when + LogEvent :: logger:log_event(), Config :: logger:config(). -log(Log,Config=#{id:=Name}) -> +log(LogEvent,Config=#{id:=Name}) -> %% if the handler has crashed, we must drop this request %% and hope the handler restarts so we can try again true = is_pid(whereis(Name)), - Bin = logger_h_common:log_to_binary(Log,Config), + Bin = logger_h_common:log_to_binary(LogEvent,Config), logger_h_common:call_cast_or_drop(Name, Bin). diff --git a/lib/kernel/src/logger_filters.erl b/lib/kernel/src/logger_filters.erl index 322aa0265d..7359b3b4b7 100644 --- a/lib/kernel/src/logger_filters.erl +++ b/lib/kernel/src/logger_filters.erl @@ -27,13 +27,13 @@ -include("logger_internal.hrl"). -define(IS_ACTION(A), (A==log orelse A==stop)). --spec domain(Log,Extra) -> logger:filter_return() when - Log :: logger:log(), +-spec domain(LogEvent,Extra) -> logger:filter_return() when + LogEvent :: logger:log_event(), Extra :: {Action,Compare,MatchDomain}, Action :: log | stop, Compare :: super | sub | equal | not_equal | undefined, MatchDomain :: list(atom()). -domain(#{meta:=Meta}=Log,{Action,Compare,MatchDomain}) +domain(#{meta:=Meta}=LogEvent,{Action,Compare,MatchDomain}) when ?IS_ACTION(Action) andalso (Compare==super orelse Compare==sub orelse @@ -41,17 +41,17 @@ domain(#{meta:=Meta}=Log,{Action,Compare,MatchDomain}) Compare==not_equal orelse Compare==undefined) andalso is_list(MatchDomain) -> - filter_domain(Compare,Meta,MatchDomain,on_match(Action,Log)); -domain(Log,Extra) -> - erlang:error(badarg,[Log,Extra]). + filter_domain(Compare,Meta,MatchDomain,on_match(Action,LogEvent)); +domain(LogEvent,Extra) -> + erlang:error(badarg,[LogEvent,Extra]). --spec level(Log,Extra) -> logger:filter_return() when - Log :: logger:log(), +-spec level(LogEvent,Extra) -> logger:filter_return() when + LogEvent :: logger:log_event(), Extra :: {Action,Operator,MatchLevel}, Action :: log | stop, Operator :: neq | eq | lt | gt | lteq | gteq, MatchLevel :: logger:level(). -level(#{level:=L1}=Log,{Action,Op,L2}) +level(#{level:=L1}=LogEvent,{Action,Op,L2}) when ?IS_ACTION(Action) andalso (Op==neq orelse Op==eq orelse @@ -60,25 +60,25 @@ level(#{level:=L1}=Log,{Action,Op,L2}) Op==lteq orelse Op==gteq) andalso ?IS_LEVEL(L2) -> - filter_level(Op,L1,L2,on_match(Action,Log)); -level(Log,Extra) -> - erlang:error(badarg,[Log,Extra]). + filter_level(Op,L1,L2,on_match(Action,LogEvent)); +level(LogEvent,Extra) -> + erlang:error(badarg,[LogEvent,Extra]). --spec progress(Log,Extra) -> logger:filter_return() when - Log :: logger:log(), +-spec progress(LogEvent,Extra) -> logger:filter_return() when + LogEvent :: logger:log_event(), Extra :: log | stop. -progress(Log,Action) when ?IS_ACTION(Action) -> - filter_progress(Log,on_match(Action,Log)); -progress(Log,Action) -> - erlang:error(badarg,[Log,Action]). +progress(LogEvent,Action) when ?IS_ACTION(Action) -> + filter_progress(LogEvent,on_match(Action,LogEvent)); +progress(LogEvent,Action) -> + erlang:error(badarg,[LogEvent,Action]). --spec remote_gl(Log,Extra) -> logger:filter_return() when - Log :: logger:log(), +-spec remote_gl(LogEvent,Extra) -> logger:filter_return() when + LogEvent :: logger:log_event(), Extra :: log | stop. -remote_gl(Log,Action) when ?IS_ACTION(Action) -> - filter_remote_gl(Log,on_match(Action,Log)); -remote_gl(Log,Action) -> - erlang:error(badarg,[Log,Action]). +remote_gl(LogEvent,Action) when ?IS_ACTION(Action) -> + filter_remote_gl(LogEvent,on_match(Action,LogEvent)); +remote_gl(LogEvent,Action) -> + erlang:error(badarg,[LogEvent,Action]). %%%----------------------------------------------------------------- %%% Internal @@ -123,5 +123,5 @@ filter_remote_gl(#{meta:=#{gl:=GL}},OnMatch) when node(GL)=/=node() -> filter_remote_gl(_,_) -> ignore. -on_match(log,Log) -> Log; +on_match(log,LogEvent) -> LogEvent; on_match(stop,_) -> stop. diff --git a/lib/kernel/src/logger_formatter.erl b/lib/kernel/src/logger_formatter.erl index 5882c70ddf..95cb6e35fc 100644 --- a/lib/kernel/src/logger_formatter.erl +++ b/lib/kernel/src/logger_formatter.erl @@ -30,8 +30,8 @@ %%%----------------------------------------------------------------- %%% API --spec format(Log,Config) -> unicode:chardata() when - Log :: logger:log(), +-spec format(LogEvent,Config) -> unicode:chardata() when + LogEvent :: logger:log_event(), Config :: #{single_line=>boolean(), legacy_header=>boolean(), report_cb=>fun((logger:report()) -> {io:format(),[term()]}), diff --git a/lib/kernel/src/logger_h_common.erl b/lib/kernel/src/logger_h_common.erl index 70531c0e34..336398cd4a 100644 --- a/lib/kernel/src/logger_h_common.erl +++ b/lib/kernel/src/logger_h_common.erl @@ -39,8 +39,8 @@ %%%----------------------------------------------------------------- %%% Covert log data on any form to binary --spec log_to_binary(Log,Config) -> LogString when - Log :: logger:log(), +-spec log_to_binary(LogEvent,Config) -> LogString when + LogEvent :: logger:log_event(), Config :: logger:config(), LogString :: binary(). log_to_binary(#{msg:={report,_},meta:=#{report_cb:=_}}=Log,Config) -> @@ -58,7 +58,7 @@ do_log_to_binary(Log,Config) -> catch _:_ -> ?LOG_INTERNAL(debug,[{formatter_error,Formatter}, {config,FormatterConfig}, - {log,Log}, + {log_event,Log}, {bad_return_value,String}]), <<"FORMATTER ERROR: bad_return_value">> end. @@ -69,7 +69,7 @@ try_format(Log,Formatter,FormatterConfig) -> C:R:S -> ?LOG_INTERNAL(debug,[{formatter_crashed,Formatter}, {config,FormatterConfig}, - {log,Log}, + {log_event,Log}, {reason, {C,R,logger:filter_stacktrace(?MODULE,S)}}]), case {?DEFAULT_FORMATTER,#{}} of diff --git a/lib/kernel/src/logger_std_h.erl b/lib/kernel/src/logger_std_h.erl index fc8ca1535b..63c3ab2dac 100644 --- a/lib/kernel/src/logger_std_h.erl +++ b/lib/kernel/src/logger_std_h.erl @@ -219,15 +219,15 @@ swap_buffer(Name,Buffer) -> %%%----------------------------------------------------------------- %%% Log a string or report --spec log(Log, Config) -> ok | dropped when - Log :: logger:log(), +-spec log(LogEvent, Config) -> ok | dropped when + LogEvent :: logger:log_event(), Config :: logger:config(). -log(Log,Config=#{id:=Name}) -> +log(LogEvent,Config=#{id:=Name}) -> %% if the handler has crashed, we must drop this request %% and hope the handler restarts so we can try again true = is_pid(whereis(Name)), - Bin = logger_h_common:log_to_binary(Log,Config), + Bin = logger_h_common:log_to_binary(LogEvent,Config), logger_h_common:call_cast_or_drop(Name, Bin). %%%=================================================================== diff --git a/lib/kernel/test/logger_formatter_SUITE.erl b/lib/kernel/test/logger_formatter_SUITE.erl index eaa6c0aca5..7a93f2ca79 100644 --- a/lib/kernel/test/logger_formatter_SUITE.erl +++ b/lib/kernel/test/logger_formatter_SUITE.erl @@ -514,7 +514,7 @@ level_or_msg_in_meta(_Config) -> ok. faulty_log(_Config) -> - %% Unexpected log (should be type logger:log()) - print error + %% Unexpected log (should be type logger:log_event()) - print error {error, function_clause, {logger_formatter,format,[_,_],_}} = -- cgit v1.2.3 From 53539ee751da408029c9dfae80384fdec6c7a552 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Tue, 22 May 2018 13:22:55 +0200 Subject: Update documentation of logger and error_logger --- lib/kernel/doc/src/error_logger.xml | 233 ++++++++++------ lib/kernel/doc/src/kernel_app.xml | 8 +- lib/kernel/doc/src/logger.xml | 44 ++- lib/kernel/doc/src/logger_chapter.xml | 477 ++++++++++++++++++++------------ lib/kernel/doc/src/logger_formatter.xml | 370 +++++++++++++------------ lib/kernel/src/logger.erl | 4 +- lib/kernel/src/logger_formatter.erl | 21 +- lib/sasl/doc/src/sasl_app.xml | 4 +- lib/stdlib/doc/src/proc_lib.xml | 17 +- 9 files changed, 708 insertions(+), 470 deletions(-) (limited to 'lib') diff --git a/lib/kernel/doc/src/error_logger.xml b/lib/kernel/doc/src/error_logger.xml index e91fc734a4..f418aa5bbe 100644 --- a/lib/kernel/doc/src/error_logger.xml +++ b/lib/kernel/doc/src/error_logger.xml @@ -33,9 +33,10 @@ -

In OTP-21, a new API for logging was added to Erlang/OTP. The +

In Erlang/OTP 21.0, a new API for logging was added. The old error_logger module can still be used by legacy - code, but new code should use the new API instead.

+ code, but log events are redirected to the new Logger API. New + code should use the Logger API directly.

error_logger is no longer started by default, but is automatically started when an event handler is added with error_logger:add_report_handler/1,2. The error_logger @@ -89,6 +90,9 @@ The function returns ok if successful.

The event handler must be able to handle the events in this module, see section Events.

+

The first time this function is called, + error_logger is added as a Logger handler, and + the error_logger process is started.

@@ -98,37 +102,40 @@

Deletes an event handler from the error logger by calling gen_event:delete_handler(error_logger, Handler, []), see gen_event(3).

+

If no more event handlers exist after the deletion, + error_logger is removed as a Logger handler, and + the error_logger process is stopped.

- Send a standard error event to the error logger. + Log a standard error event. -

Sends a standard error event to the error logger. - The Format and Data arguments - are the same as the arguments of +

Log a standard error event. The Format + and Data arguments are the same as the + arguments of io:format/2 - in STDLIB. - The event is handled by the standard event handler.

+ in STDLIB.

+

Error logger forwards the event to Logger, including + metadata that allows backwards compatibility with legacy + error logger event handlers.

+

The event is handled by the default Logger handler.

+

These functions are kept for backwards compatibility and + must not be used by new code. Use the + ?LOG_ERROR macro or + logger:error/1,2,3 + instead.

Example:

-1> error_logger:error_msg("An error occurred in ~p~n", [a_module]).
-
-=ERROR REPORT==== 11-Aug-2005::14:03:19 ===
+1> error_logger:error_msg("An error occurred in ~p", [a_module]).
+=ERROR REPORT==== 22-May-2018::11:18:43.376917 ===
 An error occurred in a_module
 ok
- -

If called with bad arguments, this function can crash - the standard event handler, meaning no further events are - logged. When in doubt, use - error_report/1 - instead.

-

If the Unicode translation modifier (t) 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.

@@ -136,36 +143,51 @@ ok
- Send a standard error report event to the error logger. + Log a standard error event. -

Sends a standard error report event to the error logger. - The event is handled by the standard event handler.

+

Log a standard error event. Error logger forwards the event + to Logger, including metadata that allows backwards + compatibility with legacy error logger event handlers.

+

The event is handled by the default Logger handler.

+

This functions is kept for backwards compatibility and + must not be used by new code. Use the + ?LOG_ERROR macro or + logger:error/1,2,3 + instead.

Example:

 2> error_logger:error_report([{tag1,data1},a_term,{tag2,data}]).
-
-=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> error_logger:error_report("Serious error in my module").
-
-=ERROR REPORT==== 11-Aug-2005::13:45:49 ===
+=ERROR REPORT==== 22-May-2018::11:24:45.972445 ===
 Serious error in my module
 ok
- Send a user-defined error report event to the error logger. + Log a user-defined error event. -

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.

+

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.

+

Error logger also adds a domain field with + value [Type] 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.

It is recommended that Report follows the same structure as for error_report/1.

+

This functions is kept for backwards compatibility and + must not be used by new code. Use the + ?LOG_ERROR macro or + logger:error/1,2,3 + instead.

@@ -181,38 +203,41 @@ ok

The error_logger_format_depth variable is deprecated since - the logging API was - introduced in OTP-21. The variable, and this function, are - kept for backwards compatibility since they still might be - used by legacy report handlers.

+ the Logger API 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.

- Send a standard information event to the error logger. + Log a standard information event. -

Sends a standard information event to the error logger. - The Format and Data arguments - are the same as the arguments of +

Log a standard information event. The Format + and Data arguments are the same as the + arguments of io:format/2 - in STDLIB. The event is handled by the standard event handler.

+ in STDLIB.

+

Error logger forwards the event to Logger, including + metadata that allows backwards compatibility with legacy + error logger event handlers.

+

The event is handled by the default Logger handler.

+

These functions are kept for backwards compatibility and + must not be used by new code. Use the + ?LOG_INFO macro or + logger:info/1,2,3 + instead.

Example:

-1> error_logger:info_msg("Something happened in ~p~n", [a_module]).
-
-=INFO REPORT==== 11-Aug-2005::14:06:15 ===
+1> error_logger:info_msg("Something happened in ~p", [a_module]).
+=INFO REPORT==== 22-May-2018::12:03:32.612462 ===
 Something happened in a_module
 ok
- -

If called with bad arguments, this function can crash - the standard event handler, meaning no further events are - logged. When in doubt, use info_report/1 instead.

-

If the Unicode translation modifier (t) 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.

@@ -220,37 +245,52 @@ ok
- Send a standard information report event to the error logger. + Log a standard information event. -

Sends a standard information report event to the error - logger. The event is handled by the standard event handler.

+

Log a standard information event. Error logger forwards the + event to Logger, including metadata that allows backwards + compatibility with legacy error logger event handlers.

+

The event is handled by the default Logger handler.

+

This functions is kept for backwards compatibility and + must not be used by new code. Use the + ?LOG_INFO macro or + logger:info/1,2,3 + instead.

Example:

 2> error_logger:info_report([{tag1,data1},a_term,{tag2,data}]).
-
-=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> error_logger:info_report("Something strange happened").
-
-=INFO REPORT==== 11-Aug-2005::13:55:36 ===
+=INFO REPORT==== 22-May-2018::12:06:49.066872 ===
 Something strange happened
 ok
- Send a user-defined information report event to the error logger. + Log a user-defined information event. -

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.

+

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.

+

Error logger also adds a domain field with + value [Type] 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.

It is recommended that Report follows the same structure as for info_report/1.

+

This functions is kept for backwards compatibility and + must not be used by new code. Use the + ?LOG_INFO macro or + logger:info/1,2,3 + instead.

@@ -349,24 +389,27 @@ ok - Send a standard warning event to the error logger. + Log a standard warning event. -

Sends a standard warning event to the error logger. - The Format and Data arguments - are the same as the arguments of +

Log a standard warning event. The Format + and Data arguments are the same as the + arguments of io:format/2 - in STDLIB. - The event is handled by the standard event handler. It is tagged - as an error, warning, or info, see + in STDLIB.

+

Error logger forwards the event to Logger, including + metadata that allows backwards compatibility with legacy + error logger event handlers.

+

The event is handled by the default Logger handler. The log + level can be changed to error or info, see warning_map/0.

- -

If called with bad arguments, this function can crash - the standard event handler, meaning no further events are - logged. When in doubt, use warning_report/1 instead.

-
+

These functions are kept for backwards compatibility and + must not be used by new code. Use the + ?LOG_WARNING macro or + logger:warning/1,2,3 + instead.

If the Unicode translation modifier (t) 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.

@@ -374,24 +417,43 @@ ok
- Send a standard warning report event to the error logger. + Log a standard warning event. -

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 +

Log a standard warning event. Error logger forwards the event + to Logger, including metadata that allows backwards + compatibility with legacy error logger event handlers.

+

The event is handled by the default Logger handler. The log + level can be changed to error or info, see warning_map/0.

+

This functions is kept for backwards compatibility and + must not be used by new code. Use the + ?LOG_WARNING macro or + logger:warning/1,2,3 + instead.

- Send a user-defined warning report event to the error logger. + Log a user-defined warning event. -

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 +

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.

+

Error logger also adds a domain field with + value [Type] 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.

+

The log level can be changed to error or info, see warning_map/0.

+

It is recommended that Report follows the same + structure as for + warning_report/1.

+

This functions is kept for backwards compatibility and + must not be used by new code. Use the + ?LOG_WARNING macro or + logger:warning/1,2,3 + instead.

@@ -455,8 +517,9 @@ ok
See Also

gen_event(3), - log_mf_h(3) - kernel(6) + logger(3), + log_mf_h(3), + kernel(6), sasl(6)

diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml index 0f7e95472b..e2a6d30249 100644 --- a/lib/kernel/doc/src/kernel_app.xml +++ b/lib/kernel/doc/src/kernel_app.xml @@ -481,13 +481,13 @@ MaxT = TickTime + TickTime / 4
Deprecated Configuration Parameters -

In OTP-21, a new API for logging was added to Erlang/OTP. The +

In Erlang/OTP 21.0, a new API for logging was added. The old error_logger event manager, and event handlers - running on this manager, will still work, but they are not used + running on this manager, still work, but they are no longer used by default.

The following application configuration parameters can still be - set, but they will only be used if the corresponding new logger - variables are not set.

+ set, but they are only used if the corresponding configuration + parameters for Logger are not set.

error_logger Replaced by setting the type of the default diff --git a/lib/kernel/doc/src/logger.xml b/lib/kernel/doc/src/logger.xml index bb356c5b86..c0b3d81367 100644 --- a/lib/kernel/doc/src/logger.xml +++ b/lib/kernel/doc/src/logger.xml @@ -132,6 +132,29 @@ logger:error("error happened because: ~p",[Reason]). %% Without macro log event to the handlers. If the same keys occur, values from the log call overwrite process metadata, which in turn overwrite values set by Logger.

+

The following custom metadata keys have special meaning:

+ + domain + +

The value associated with this key is used by filters + for grouping log events originating from, for example, + specific functional + areas. See + logger_filters:domain/2 + for a description of how this field can be used.

+
+ report_cb + +

If the log message is specified as + a report(), + the report_cb key can be associated with a fun + (report callback) that converts the report to a format + string and arguments. See + section Log + Message in the User's Guide for more + information about report callbacks.

+
+
@@ -145,7 +168,7 @@ logger:error("error happened because: ~p",[Reason]). %% Without macro filters => [] formatter => {logger_formatter,DefaultFormatterConfig} -

See the +

See the logger_formatter(3) manual page for information about the default configuration for this formatter.

@@ -978,6 +1001,25 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(),Meta)).
+ + FModule:check_config(FConfig) -> ok | {error,term()} + Validate the given formatter configuration. + + FConfig = + formatter_config() + + +

This callback function is optional.

+

The function is called by a Logger when formatter + configuration is set or modified. The formatter must + validate the given configuration and return ok if it + is correct, and {error,term()} if it is faulty.

+

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

+
+
FModule:format(LogEvent,FConfig) -> FormattedLogEntry Format the given log event. diff --git a/lib/kernel/doc/src/logger_chapter.xml b/lib/kernel/doc/src/logger_chapter.xml index 3b4cafb010..a3eec7bd4b 100644 --- a/lib/kernel/doc/src/logger_chapter.xml +++ b/lib/kernel/doc/src/logger_chapter.xml @@ -30,7 +30,7 @@ logger_chapter.xml -

As of OTP-21, Erlang/OTP provides a standard API for logging +

Erlang/OTP 21.0 provides a new 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 @@ -65,63 +65,14 @@ Conceptual Overview - -

In accordance with the Syslog protocol, RFC-5424, eight log - 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 - - Log Levels -
- -

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.

+

Log levels are expressed as atoms. Internally in Logger, the + atoms are mapped to integer values, and a log event passes the + log level check if the integer value of its log level is less + than or equal to the currently configured log level. That is, + the check pases if the event is equally or more severe than the + configured level. See section Log + Level for a listing and description of all log + levels.

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.

@@ -137,13 +88,150 @@ 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.

+

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.

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

+
+ Logger API +

The API for logging consists of a set + of macros, and a set + of functions on the form logger:Level/1,2,3, which are + all shortcuts + for + logger:log(Level,Arg1[,Arg2[,Arg3]]).

+

The difference between using the macros and the exported + functions is that macros add location (originator) information + to the metadata, and performs lazy evaluation by wrapping the + logger call in a case statement, so it is only evaluated if the + log level of the event passes the global log level check.

+
+ + Log Level +

The log level indicates the severity of a event. In + accordance with the Syslog protocol, RFC-5424, eight log + levels can be specified. The following table lists all + possible log levels by name (atom), integer value, and + description:

+ + + + 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 + + Log Levels +
+

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 + logger:compare_levels/2.

+
+
+ + Log Message +

The log message contains the information to be logged. The + message can consist of a format string and arguments (given as + two separate parameters in the Logger API), a string or a + report. The latter, which is either a map or a key-value list, + can be accompanied by a report callback specified in the log + event's metadata. The + report callback is a convenience function that + the formatter can use + to convert the report to a format string and arguments. The + formatter can also use its own conversion function, if no + callback is provided, or if a customized formatting is + desired.

+

Example, format string and arguments:

+ logger:error("The file does not exist: ~ts",[Filename]) +

Example, string:

+ logger:notice("Something strange happened!") +

Example, report, and metadata with report callback:

+ +logger:debug(#{got => connection_request, id => Id, state => State}, + #{report_cb => fun(R) -> {"~p",[R]} end}) +

The log message can also be provided through a fun for lazy + evaluation. The fun is only evaluated if the global log level + check passes, and is therefore recommended if it is expensive + to generate the message. The lazy fun must return a string, a + report, or a tuple with format string and arguments.

+
+
+ Metadata +

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:

+ + Set process metadata + +

Process metadata is set and updated + with + logger:set_process_metadata/1 + and + logger:update_process metadata/1, + 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.

+
+ Add metadata to a specifc log event + +

Metadata associated with one specifc log event is given + as the last parameter to the log macro or Logger API + function when the event is issued. For example:

+ ?LOG_ERROR("Connection closed",#{context => server}) +
+
+

See the description of + the + logger:metadata() type for information + about which default keys Logger inserts, and how the different + metadata maps are merged.

+
+
Filters @@ -166,13 +254,13 @@ discarded. If the filter is global, no handler filters or callbacks are called. If it is a handler filter, the corresponding handler callback is not called, but the log event - is forwarded to the filters attached to the next handler, if + is forwarded to filters attached to the next handler, if any.

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

If the filter function returns ignore, it means that it did not recognize the log event, and thus leaves to other @@ -180,24 +268,21 @@

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.

- + return ignore, or if no filters + exist. filter_default is by default set to log, + meaning that if all existing filters ignore a log event, Logger + forwards the event to the handler + callback. If filter_default is set to stop, Logger + discards such events.

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 + be added at system start via the Kernel configuration parameter logger.

-

Handler filters are added with +

Handler filters are added with logger:add_handler_filter/3 and removed @@ -206,7 +291,7 @@ be specified directly in the configuration when adding a handler with logger:add_handler/3 - or via Kernel configuration + or via the Kernel configuration parameter logger.

To see which filters are currently installed in the system, @@ -215,35 +300,37 @@ logger:get_logger_config/0 and logger:get_handler_config/1. Filters are - applied in the order they are listed.

+ listed in the order they are applied, that is, the first + filter in the list is applied first, and so on.

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:domain/2 + +

Provides a way of filtering log events based on a + domain field in 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.

+
+
@@ -252,19 +339,19 @@

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

-
log(LogEvent, Config)
+
log(LogEvent, Config) -> void()

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.

+ processes are 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.

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

In addition to the mandatory callback function log/2, a handler module can export the optional callback @@ -281,20 +368,19 @@

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.

+ given destination, terminal or file.

logger_disk_log_h -

This handler behaves much like logger_std_h, except it uses +

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 +

This handler is provided 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 @@ -302,7 +388,8 @@ 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.

+ SASL still exist, but they are not added by Erlang/OTP 21.0 + or later.

@@ -312,9 +399,10 @@ 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 + handler's destination. The handler callback receives the + formatter information as part of 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 @@ -322,9 +410,23 @@ following function, which can be called by the handler:

format(LogEvent,FConfig)
 	-> FormattedLogEntry
-

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

+

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 + logger:set_handler_config(HandlerId,formatter,{FModule,FConfig}) + , which overwrites the current formatter information, + or with + logger:update_formatter_config/2,3, which + only modifies the formatter configuration.

+

If the formatter module exports the optional callback + function + check_config(FConfig), Logger calls this + function when the formatter information is set or modified, to + verify the validity of the formatter configuration.

+

If no formatter information is specified for a handler, Logger + uses + logger_formatter(3) as default.

@@ -335,7 +437,7 @@ or at run-time by using the logger(3) API. The recommended approach is to do the initial configuration in the sys.config file and then use the API when some configuration - has to be changed at run-time, such as the log level.

+ has to be changed at runtime, such as the log level.

Kernel Configuration Parameters @@ -436,9 +538,9 @@ logger:level()

Specifies the global log level to log.

-

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

+

See section Log + Level for a listing and description of + possible log levels.

The initial value of this option is set by the Kernel configuration parameter @@ -465,7 +567,7 @@ filter_default = log | stop

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

+ return ignore, or if no filters exist.

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

Default is log.

@@ -481,9 +583,9 @@ logger:level()

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.

+

See section Log + Level 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, @@ -509,7 +611,7 @@ filter_default = log | stop

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

+ return ignore, or if no filters exist.

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

Default is log.

@@ -553,14 +655,14 @@
Backwards Compatibility with error_logger -

Logger provides backwards compatibility with the old +

Logger provides backwards compatibility with error_logger in the following ways:

API for Logging -

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

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

Calls to @@ -585,7 +687,7 @@

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 + configuration parameter legacy_header => true. This is also the default.

Default Format of Log Events from OTP @@ -608,10 +710,11 @@ configuration parameters.

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 behaviour is as follows:

+

As of Erlang/OTP 21.0, the concept of SASL reports is + removed, meaning that the default behaviour is as + follows:

- Supervisor reports, crash reports and progress reports + Supervisor reports, crash reports, and progress reports are no longer connected to the SASL application. Supervisor reports and crash reports are logged by default. @@ -626,15 +729,15 @@ parameter logger_sasl_compatible can be set to true. The - old SASL + SASL configuration parameters 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.

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

+ log events.

See the SASL User's Guide for more information about the old SASL error logging functionality.

@@ -650,14 +753,14 @@ error_logger:add_report_handler/1,2. event manager, and add error_logger as a handler to logger, with configuration

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

Notice 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 + originate from the 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 notice that error_logger is not overload protected.

@@ -676,8 +779,9 @@ error_logger:add_report_handler/1,2. arguments by the handler. If a report is given, a default report callback can be included in the log event's metadata. The handler can use this callback for converting the report to a - format string and arguments. The handler might also do a custom - conversion if the default format is not desired.

+ format string and arguments. If the format obtained by the + provided callback is not desired, or if there is no provided + callback, the handler must do a custom conversion.

Logger does, to a certain extent, check its input data before forwarding a log event to the handlers, but it does not evaluate conversion funs or check the validity of format strings @@ -686,18 +790,17 @@ error_logger:add_report_handler/1,2. that it does not crash due to bad input data or faulty callbacks.

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.

+ filter or handler in question from the configuration, and print + a short error message to the terminal. A debug event containing + the crash reason and other details is also issued, and can be + seen if a handler logging debug events is installed.

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

When starting an erlang node, the default behaviour is that all +

When starting an Erlang node, the default behaviour is that all log events with level info and above are logged to the - console. In order to also log debug events, you can either + terminal. In order to also log debug events, you can either change the global log level to 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.

@@ -705,28 +808,32 @@ error_logger:add_report_handler/1,2. type {file,File}, and we set the handler's level to debug:

-1> Config = #{level=>debug,logger_std_h=>#{type=>{file,"./debug.log"}}}.
+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 - (filter_defalt=log), so we need to add a filter to stop - all non-debug events:

+ (filter_default=log, see + section Filters for more + details), so we need to add a filter to stop all non-debug + events. The built-in + filter + logger_filters:level/2 + is used for this:

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

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

-5> logger:set_logger_config(level,debug).
+4> 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).
+5> logger:set_module_level(mymodule,debug).
 ok
@@ -736,29 +843,31 @@ ok

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

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

It may also implement the following callbacks:

+

It can optionally also implement the following callbacks:

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

When logger:add_handler(Id,Module,Config) is called, Logger - will first call HModule:adding_handler(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 HModule:log/2.

+

When logger:add_handler(Id,Module,Config) is called, + Logger first calls HModule:adding_handler(Config). If + this function returns {ok,NewConfig}, Logger + writes NewConfig to the configuration database, and + the logger:add_handler/3 call returns. After this, the + handler is installed and must be ready to receive log events as + calls to HModule:log/2.

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

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

+ this function returns {ok,NewConfig}, Logger + writes NewConfig to the configuration database.

-

A simple handler that prints to the console could be - implemented as follows:

+

A simple handler that prints to the terminal can be implemented + as follows:

-module(myhandler). -export([log/2]). @@ -776,7 +885,7 @@ log(LogEvent,#{formatter:={FModule,FConfig}) -> adding_handler(Config) -> {ok,Fd} = file:open(File,[append,{encoding,utf8}]), - {ok,Config#{myhandler_fd=>Fd}}. + {ok,Config#{myhandler_fd => Fd}}. removing_handler(#{myhandler_fd:=Fd}) -> _ = file:close(Fd), @@ -790,10 +899,12 @@ log(LogEvent,#{myhandler_fd:=Fd,formatter:={FModule,FConfig}}) -> protection, and all log events are printed directly from the client process.

-

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

For information and examples of overload protection, please + refer to + section Protecting the + Handler from Overload, and the implementation + of logger_std_h(3) + and logger_disk_log_h(3) .

Below is a simpler example of a handler which logs through one @@ -805,7 +916,7 @@ log(LogEvent,#{myhandler_fd:=Fd,formatter:={FModule,FConfig}}) -> adding_handler(Config) -> {ok,Pid} = gen_server:start(?MODULE,Config), - {ok,Config#{myhandler_pid=>Pid}}. + {ok,Config#{myhandler_pid => Pid}}. removing_handler(#{myhandler_pid:=Pid}) -> gen_server:stop(Pid). @@ -815,7 +926,7 @@ log(LogEvent,#{myhandler_pid:=Pid} = Config) -> init(#{myhandler_file:=File}) -> {ok,Fd} = file:open(File,[append,{encoding,utf8}]), - {ok,#{file=>File,fd=>Fd}}. + {ok,#{file => File, fd => Fd}}. handle_call(_,_,State) -> {reply,{error,bad_request},State}. @@ -949,7 +1060,7 @@ logger:add_handler(my_standard_h, logger_std_h, both built-in handlers offer the possibility to set a maximum level of how many requests to process with a certain time frame. With this burst control feature enabled, the handler will take care of bursts of log requests - without choking log files, or the console, with massive amounts of + without choking log files, or the terminal, with massive amounts of printouts. These are the configuration parameters:

diff --git a/lib/kernel/doc/src/logger_formatter.xml b/lib/kernel/doc/src/logger_formatter.xml index ee43634cf9..02f89b26be 100644 --- a/lib/kernel/doc/src/logger_formatter.xml +++ b/lib/kernel/doc/src/logger_formatter.xml @@ -46,97 +46,150 @@ Logger.

-
- Configuration -

The configuration term for logger_formatter is a - map, - and the following keys can be set as configuration - parameters:

- - chars_limit = pos_integer() | unlimited - -

A positive integer representing the value of the option - with the same name to be used when calling - io_lib:format/3. - 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 max_size.

-

Default is unlimited.

- -

chars_limit has no effect on log messages on - string form. These are expected to be short, but can still - be truncated by the max_size parameter.

-
-
- depth = pos_integer() | unlimited - -

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,3 - in STDLIB.

-

Default is unlimited.

- -

depth has no effect on log messages on string - form. These are expected to be short, but can still be - truncated by the max_size parameter.

-
-
- max_size = pos_integer() | unlimited - -

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 chars_limit or depth, it is truncated.

-

Default is unlimited.

-
- single_line = boolean() - -

If set to true, all newlines in the message are - replaced with ", ", and whitespaces following - directly after newlines are removed. Note that newlines - added by the template parameter are not replaced.

-

Default is true.

-
- legacy_header = boolean() - -

If set to 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. See - section Default - Templates for more information.

-

Default is false.

-
- report_cb = fun((logger:report()) -> {io:format(),[term()]}) - -

A report callback is used by the formatter to transform log - messages on report form to a format string and - arguments. The report callback can be specified in the - metadata for the log event. If no report callback exist in - metadata, logger_formatter will - use - logger:format_report/1 as default - callback.

-

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.

-

The value must be a function with arity 1, - returning {Format,Args}, and it will be called with a - report as only argument.

-
- template = template() - + + + + + +

The configuration term for logger_formatter is a + map, and the + following keys can be set as configuration parameters:

+ + chars_limit = pos_integer() | unlimited + +

A positive integer representing the value of the option + with the same name to be used when calling + + io_lib:format/3. + 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 max_size.

+

Defaults to unlimited.

+ +

chars_limit has no effect on log messages on + string form. These are expected to be short, but can + still be truncated by the max_size + parameter.

+
+
+ depth = pos_integer() | unlimited + +

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,3 + in STDLIB.

+

Defaults to unlimited.

+ +

depth has no effect on log messages on string + form. These are expected to be short, but can still be + truncated by the max_size parameter.

+
+
+ legacy_header = boolean() + +

If set to 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. See the description of + the template() + type for more information.

+

Defaults to false.

+
+ max_size = pos_integer() | unlimited + +

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 chars_limit or depth, it is truncated.

+

Defaults to unlimited.

+
+ report_cb = fun((logger:report()) -> {io:format(),[term()]}) + +

A report callback is used by the formatter to transform + log messages on report form to a format string and + arguments. The report callback can be specified in the + metadata for the log event. If no report callback exist + in metadata, logger_formatter will + use + logger:format_report/1 as default + callback.

+

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.

+

The value must be a function with arity 1, + returning {Format,Args}, and it will be called + with a report as only argument.

+
+ single_line = boolean() + +

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

+

Defaults to true.

+
+ template = template() + +

The template describes how the formatted string is + composed by combining different data values from the log + event. See the description of + the template() + type for more information about this.

+
+ time_designator = byte() + +

Timestamps are formatted according to RFC3339, and the + time designator is the character used as date and time + separator.

+

Defaults to $T.

+

The value of this parameter is used as + the time_designator option + to + calendar:system_time_to_rcf3339/2.

+
+ time_offset = integer() | [byte()] + +

The time offset, either a string or an integer, to be + used when formatting the timestamp.

+

An empty string is interpreted as local time. The + values "Z", "z" or 0 are + interpreted as Universal Coordinated Time (UTC).

+

Strings, other than "Z", "z", + or "", must be on the form ±[hh]:[mm], for + example "-02:00" or "+00:00".

+

Integers must be in microseconds, meaning that the + offset 7200000000 is equivalent + to "+02:00".

+

Defaults to an empty string, meaning that timestamps + are displayed in local time. However, for backwards + compatibility, if the SASL configuration + parameter + utc_log=true, the default is + changed to "Z", meaning that timestamps are displayed + in UTC.

+

The value of this parameter is used as + the offset option + to + calendar:system_time_to_rcf3339/2.

+
+
+
+
+ + +

The template is a list of atoms, tuples and strings. The atoms level or msg, are treated as placeholders for the severity level and the log message, - repectively. Other atoms or tuples are interpreted as + respectively. Other atoms or tuples are interpreted as placeholders for metadata, where atoms are expected to match top level keys, and tuples represent paths to sub keys when the metadata is a nested map. For example the @@ -154,120 +207,84 @@

Strings in the template are printed literally.

The default template differs depending on the values of legacy_header - and single_line. See Default - Templates for more information

-
- time_designator = byte() - -

Timestamps are formatted according to RFC3339, and the time - designator is the character used as date and time - separator.

-

Default is $T.

-

The value of this parameter is used as - the time_designator option - to - calendar:system_time_to_rcf3339/2.

-
- time_offset = integer() | [byte()] - -

The time offset, either a string or an integer, to be - used when formatting the timestamp.

-

An empty string is interpreted as local time. The - values "Z", "z" or 0 are interpreted as - Universal Coordinated Time (UTC).

-

Strings, other than "Z", "z", or "", - must be on the form ±[hh]:[mm], for - example "-02:00" or "+00:00".

-

Integers must be in microseconds, meaning that the - offset 7200000000 is equivalent - to "+02:00".

-

The default value is an empty string, meaning that - timestamps are displayed in local time. However, for - backwards compatibility, if the SASL configuration - parameter - utc_log=true, the default is - changed to "Z", meaning that timestamps are displayed - in UTC.

-

The value of this parameter is used as the offset - option to - calendar:system_time_to_rcf3339/2.

-
-
-
- -
- - Default templates + and single_line:

-

The default value for the template configuration - parameter depends on the value of single_line - and legacy_header as follows.

+

The default value for the template configuration + parameter depends on the value of the single_line + and legacy_header configuration parameters as + follows.

-

The log event used in the examples is:

- +

The log event used in the examples is:

+ ?LOG_ERROR("name: ~p~nexit_reason: ~p",[my_name,"It crashed"]) - - legacy_header=true, single_line=false - -

Default template: [{logger_formatter,header},"\n",msg,"\n"]

+ + legacy_header=true, single_line=false + +

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

-

Example log entry:

- +

Example log entry:

+ =ERROR REPORT==== 17-May-2018::18:30:19.453447 === name: my_name exit_reason: "It crashed" -

Notice that all eight levels can occur in the heading, - not only ERROR, WARNING or INFO as the - old error_logger produced. And microseconds are - added at the end of the timestamp.

-
+

Notice that all eight levels can occur in the heading, + not only ERROR, WARNING or INFO as the + old error_logger produced. And microseconds are + added at the end of the timestamp.

+
- legacy_header=true, single_line=true - -

Default template: [{logger_formatter,header},"\n",msg,"\n"]

+ legacy_header=true, single_line=true + +

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

-

Notice that the template is here the same as - for single_line=false, but the resulting log entry - differs in that there is only one line after the - heading:

- +

Notice that the template is here the same as + for single_line=false, but the resulting log entry + differs in that there is only one line after the + heading:

+ =ERROR REPORT==== 17-May-2018::18:31:06.952665 === name: my_name, exit_reason: "It crashed" -
+
- legacy_header=false, single_line=true - -

Default template: [time," ",level,": ",msg,"\n"]

+ legacy_header=false, single_line=true + +

Default template: [time," ",level,": ",msg,"\n"]

-

Example log entry:

- +

Example log entry:

+ 2018-05-17T18:31:31.152864+02:00 error: name: my_name, exit_reason: "It crashed" -
+
- legacy_header=false, single_line=false - -

Default template: [time," ",level,":\n",msg,"\n"]

+ legacy_header=false, single_line=false + +

Default template: [time," ",level,":\n",msg,"\n"]

-

Example log entry:

- +

Example log entry:

+ 2018-05-17T18:32:20.105422+02:00 error: name: my_name exit_reason: "It crashed" -
-
-
- - - - - +
+ + + + Validates the given formatter configuration. + +

This callback function is called by Logger when the + formatter configuration for a handler is set or modified. It + returns ok if the configuration is valid, + and {error,term()} if it is faulty.

+
+
Formats the given message. @@ -290,7 +307,6 @@ exit_reason: "It crashed"
- diff --git a/lib/kernel/src/logger.erl b/lib/kernel/src/logger.erl index 12f8dd77cf..3beb3102fa 100644 --- a/lib/kernel/src/logger.erl +++ b/lib/kernel/src/logger.erl @@ -81,7 +81,9 @@ mfa => {module(),atom(),non_neg_integer()}, file => file:filename(), line => non_neg_integer(), - term() => term()}. + domain => [atom()], + report_cb => fun((report()) -> {io:format(),[term()]}), + atom() => term()}. -type location() :: #{mfa := {module(),atom(),non_neg_integer()}, file := file:filename(), line := non_neg_integer()}. diff --git a/lib/kernel/src/logger_formatter.erl b/lib/kernel/src/logger_formatter.erl index 95cb6e35fc..4d727b3da0 100644 --- a/lib/kernel/src/logger_formatter.erl +++ b/lib/kernel/src/logger_formatter.erl @@ -26,21 +26,22 @@ %%%----------------------------------------------------------------- %%% Types +-type config() :: #{chars_limit=>pos_integer()| unlimited, + depth=>pos_integer() | unlimited, + legacy_header=>boolean(), + max_size=>pos_integer() | unlimited, + report_cb=>fun((logger:report()) -> {io:format(),[term()]}), + single_line=>boolean(), + template=>template(), + time_designator=>byte(), + time_offset=>integer()|[byte()]}. -type template() :: [atom()|tuple()|string()]. %%%----------------------------------------------------------------- %%% API -spec format(LogEvent,Config) -> unicode:chardata() when LogEvent :: logger:log_event(), - Config :: #{single_line=>boolean(), - legacy_header=>boolean(), - report_cb=>fun((logger:report()) -> {io:format(),[term()]}), - chars_limit=>pos_integer()| unlimited, - max_size=>pos_integer() | unlimited, - depth=>pos_integer() | unlimited, - template=>template(), - time_designator=>byte(), - time_offset=>integer()|[byte()]}. + Config :: config(). format(#{level:=Level,msg:=Msg0,meta:=Meta},Config0) when is_map(Config0) -> Config = add_default_config(Config0), @@ -322,6 +323,8 @@ offset_to_utc([$+|Tz]) -> offset_to_utc(_) -> false. +-spec check_config(Config) -> ok | {error,term()} when + Config :: config(). check_config(Config) when is_map(Config) -> do_check_config(maps:to_list(Config)); check_config(Config) -> diff --git a/lib/sasl/doc/src/sasl_app.xml b/lib/sasl/doc/src/sasl_app.xml index 7f4ceeb354..be275879ee 100644 --- a/lib/sasl/doc/src/sasl_app.xml +++ b/lib/sasl/doc/src/sasl_app.xml @@ -92,9 +92,9 @@
Deprecated Error Logger Event Handlers and Configuration -

In OTP-21, a new API for logging was added to Erlang/OTP. The +

In Erlang/OTP 21.0, a new API for logging was added. The old error_logger event manager, and event handlers - running on this manager, will still work, but they are not used + running on this manager, still work, but they are not used by default.

The error logger event handlers sasl_report_tty_h and sasl_report_file_h, were earlier used for printing diff --git a/lib/stdlib/doc/src/proc_lib.xml b/lib/stdlib/doc/src/proc_lib.xml index c4fdf972e4..51380ae51c 100644 --- a/lib/stdlib/doc/src/proc_lib.xml +++ b/lib/stdlib/doc/src/proc_lib.xml @@ -61,8 +61,9 @@ shutdown, or {shutdown,Term}), a crash report is generated, which is written to terminal by the default logger handler setup by Kernel. For more information about how crash reports - were logged before OTP-21, see - SASL Error Logging in the SASL User's Guide.

+ were logged prior to Erlang/OTP 21.0, see + SASL Error Logging + in the SASL User's Guide.

Unlike in "plain Erlang", proc_lib processes will not generate error reports, which are written to the terminal by the @@ -118,9 +119,9 @@ the error_logger is no longer the preferred interface for logging in Erlang/OTP. A new logging - API was added in OTP-21, but - legacy error_logger handlers may still be used. New - logger handlers do not need to used this function, since + API was added in Erlang/OTP 21.0, but + legacy error_logger handlers can still be used. New + Logger handlers do not need to use this function, since the formatting callback (report_cb) is included as metadata in the log event.

@@ -145,9 +146,9 @@ the error_logger is no longer the preferred interface for logging in Erlang/OTP. A new logging - API was added in OTP-21, but - legacy error_logger handlers may still be used. New - logger handlers do not need to used this function, since + API was added in Erlang/OTP 21.0, but + legacy error_logger handlers can still be used. New + Logger handlers do not need to used this function, since the formatting callback (report_cb) is included as metadata in the log event.

-- cgit v1.2.3