# Logging

To use logger in your module, include

```erlang
-include("mongoose_logger.hrl").
```
or
```erlang
-include("mongoose.hrl").
```

## Logging macros

There are several macros for the most common logging levels:

```erlang
?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"`.

```toml
[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](https://ferd.ca/erlang-otp-21-s-new-logger.html).
We also use a modified [logfmt](https://brandur.org/logfmt) format as one of
the possible default logger formatters.
This format is [Splunk](https://www.splunk.com/en_us/devops.html) and [ELK](https://www.elastic.co/elk-stack) friendly.
Check [the list of fields](../operation-and-maintenance/Logging-fields.md) for fields documentation.

`what => something_interesting` field is required.

```erlang
    ?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:

```erlang
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:

```erlang
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.
