The Erlang logger application introduced in OTP 21 is extremely flexible, but the default settings are not the most practical for development purposes:

  • The default log level is notice, meaning that info and debug messages will not be printed.
  • Log messages with a domain other than [otp] will not be printed.
  • Each printed log message will start with a cumbersome banner, e.g. =NOTICE REPORT==== 15-Nov-2020::11:20:10.421265 ===.

While it is possible to change logger settings in the system configuration file, it means that it has to be done for each project you work on.

Fortunately, Erlang has the ability to load and execute code from a file at $HOME/.erlang. For example, I use the following code to configure the logger:

LogHandler = #{level => debug,
               filter_default => log,
               filters => [{remote_group_leader,
                            {fun logger_filters:remote_gl/2, stop}},
                           {progress,
                            {fun logger_filters:progress/2, stop}},
                           {sasl,
                            {fun logger_filters:domain/2,
                             {stop, sub, [otp, sasl]}}}],
               formatter => {logger_formatter,
                             #{single_line => false,
                               template =>
                                   [domain, " ", level, ": ", msg, "\n"]}}},
application:set_env(kernel, logger,
                    [{handler, default, logger_std_h, LogHandler}]),
application:set_env(kernel, logger_level, debug),
logger:set_handler_config(default, LogHandler).

For development, I went with the following settings:

  • All messages are logged. Debug logging can still be disabled on a per-project basis (using a local system configuration file) for applications which are too verbose.
  • Remote messages and progress messages are dropped, they are usually useless during development.
  • SASL messages are also dropped by default, they tend to be quite redundant.
  • We keep multi-line display, which is really useful to read stack traces.
  • Log messages are prefixed by the domain (see the documentation for more information about domains) and the log level.

Note that while this setup will work with erl, the Rebar3 shell requires some adjustments.

Rebar3 must be installed from source with a start script, because the packaged escript-based version does not load $HOME/.erlang. There is an open issue, but in the mean time, you can install Rebar3 from source:

  • Clone the repository.
  • Build Rebar3: ./bootstrap.
  • Install it locally: ./rebar3 local install. Note that ./rebar3 local upgrade will not use the code you just built, but will always fetch a stable release from the internet.
  • Add $HOME/.cache/rebar3/bin to your PATH environment variable.

There is also an issue with logger configuration reloading in the shell. I created a PR, but in the mean time you will need to apply this patch.

Finally, if you load extra system configuration files with the --config command line option, you will have to make sure that any logger modification performed in $HOME/.erlang is also applied to system configuration (e.g. with application:set_env/3), since Rebar3 will reload the logger configuration from the environment, ignoring any live setting.