Illegal_config_change when trying to redirect logger to standard error

Hello, I’m trying to redirect logs to standard error:

logger:set_handler_config(default, config, #{type => {device, standard_error}}

and I’m getting the illegal_config_change error. Currently, I’m removing the handler and adding it back, but feels like a workaround for such a simple thing. Any chance that redirecting the default handler to the standard error could be supported?


I don’t see any issues with allowing that. It was probably an oversight when Allow using custom IO devices in logger_std_h by hauleth · Pull Request #2523 · erlang/otp · GitHub was implemented.

Don’t know when/if I will look at it, a PR would speed up the process.

Actually I need to retract that. It is not, and should not, be possible to change the type after a logger handler has been added. Allowing that would open up for issues with lost log messages which is not something that we want.

The correct way would be to start the system with the kernel config already set to the correct device.

The correct way would be to start the system with the kernel config already set to the correct device.

Thanks for clarification. How can I do it?

You do it the same way as a file logger. That is:

## On the command line
> erl -kernel logger '[{handler, default, logger_std_h, #{config => #{type => {device, standard_error} }}}]' 
## Or in a config file
> cat sys.config 
    [{handler, default, logger_std_h,
      #{config => #{type => {device, standard_error}}}}]
> erl -config sys

It is mentioned in the Logger Description and in more details in Configuration section of the logger User’s Guide.

Thanks! My use case is quite specific, as I’m creating an Elixir script that people can use and/or adjust, and it’s meant to be used within a Unix pipeline, like

cat file.txt | elixir transform.exs | less

And I need to redirect the logs so they don’t interfere with the script’s output. Any chance that this can be achieved more concisely? I can’t imagine people writing

cat file.txt | elixir --erl "-kernel logger '[{handler, default, logger_std_h, #{config => #{type => {device, standard_error} }}}]'" | less

Or maybe my approach is generally wrong?

I don’t know how to achieve it using elixir scripts, for erlang scripts you can pass it as part of the top arguments.

#!/usr/bin/env escript
%%! -kernel logger '[{handler, default, logger_std_h, #{config => #{type => {device, standard_error} }}}]' 
main(...) -> ok.
1 Like

I’ll look into this, thanks a lot for your help!