Logging

To use logger in your module, include

-include("mongoose_logger.hrl").

or

-include("mongoose.hrl").

Logging macros

There are several macros for the most common logging levels:

?LOG_DEBUG(#{what => debug_event, info => Arg}),
?LOG_INFO(#{what => info_event, info => Arg}),
?LOG_NOTICE(#{what => notice_event, info => Arg}),
?LOG_WARNING(#{what => warning_event, info => Arg}),
?LOG_ERROR(#{what => error_event, info => Arg}),
?LOG_CRITICAL(#{what => critical_event, info => Arg}),

Use them in correspondence with the appropriate log level. Please be mindful of what is logged and which log level is used for it.

Logging levels

A system operator can choose the global log level by setting loglevel in mongooseim.toml.

Possible values are the standard syslog severity levels, plus all or none: "all", "debug", "info", "notice", "warning", "error", "critical", "alert", "emergency", and "none".

[general]
  loglevel = "notice"

If a user sets the log level to all, then they would see all messages in logs.

Levels warning and error are the most commonly used for production systems.

Logging format

We use structured logging as inspired by Ferd's post. We also use a modified logfmt format as one of the possible default logger formatters. This format is Splunk and ELK friendly. Check the list of fields for fields documentation.

what => something_interesting field is required.

    ?LOG_ERROR(#{what => check_password_failed,
                 reason => Error, user => LUser})

    try ...
    catch
        Class:Reason:StackTrace ->
            ?LOG_ERROR(#{what => check_password_failed,
                         class => Class, reason => Reason, stacktrace => StackTrace}),
            erlang:raise(Class, Reason, StackTrace)
    end

Field user => <<"alice">> is often used too.

A common way to name an error event is what => function_name_failed. For example, what => remove_user_failed. Use the advice critically, it would not work well for any function. Counterexample:

handle_info(Info, State) ->
    ?LOG_WARNING(#{what => unexpected_message, msg => Info}),
    {noreply, State}.

Filtering logs by module

Setting loglevel to debug can lead to a flood of messages in logs. To set a different loglevel for just one module, call:

mongoose_logs:set_global_loglevel(error).
mongoose_logs:set_module_loglevel(mod_mam, debug).

This code sets the loglevel to error for all log messages, except for those generated by mod_mam. All messages from mod_mam would be logged.