Koszal

Koszal

How to log to stderr?

I am trying to write log messages to stderr (rather than to stdout). However, the obvious thing (device: :standard_error) seems to have no effect. In the following one-liner the log output is still written to stdout.

$ elixir -e 'require Logger; Logger.configure_backend(:console, device: :standard_error); Logger.error("why stdout?")' 2>/dev/null 

20:41:11.210 [error] why stdout?

Am I missing something obvious?

I wanted to create a script that writes something to stdout and then that something is piped into another program. Hence the logger must write to stderr (rather than stdout).

Koszal

Most Liked

dwark

dwark

There have been indeed some changes to Elixir’s Logger since v1.15.0:

[Logger] The :console configuration has been deprecated in favor of :default_formatter
[Logger] The :backends configuration has been deprecated in favor of Logger.add_handlers/1

Logger now uses :logger’s default handler and refers to the logger_std_h documentation, which states:

type = io:standard_io/0 | io:standard_error/0 | file | {device, io:device/0 } - Specifies the log destination.

The value is set when the handler is added, and it cannot be changed in runtime.

Defaults to standard_io, unless parameter file is given, in which case it defaults to file.

So once the require Logger is excuted in the one-liner, the default handler will have been added and its device cannot be changed during runtime. And looking at the actual
configuration of the default handler:

elixir -e 'require Logger; :logger.get_handler_config(:default) |> IO.inspect(); Logger.error("why stdout?")' 2>scr/delme
{:ok,
 %{
   id: :default,
   module: :logger_std_h,
   config: %{
     type: :standard_io,
     burst_limit_enable: true,
     drop_mode_qlen: 200,
     flush_qlen: 1000,
     sync_mode_qlen: 10,
     overload_kill_restart_after: 5000,
     burst_limit_max_count: 500,
     burst_limit_window_time: 1000,
     overload_kill_enable: false,
     overload_kill_mem_size: 3000000,
     overload_kill_qlen: 20000,
     filesync_repeat_interval: :no_repeat
   },
   level: :all,
   filters: [remote_gl: {&:logger_filters.remote_gl/2, :stop}],
   filter_default: :log,
   formatter: {Logger.Formatter,
    %Logger.Formatter{
      template: ["\n", :time, " ", :metadata, "[", :level, "] ", :message, "\n"],
      truncate: 8096,
      metadata: [],
      colors: %{
        error: :red,
        enabled: true,
        info: :normal,
        warning: :yellow,
        debug: :cyan,
        notice: :normal,
        alert: :red,
        critical: :red,
        emergency: :red
      },
      utc_log?: false
    }}
 }}

08:53:01.187 [error] why stdout?

it is indeed using stdio.

hauleth

hauleth

It is possible. You just need to add additional Logger backend that will filter messages to level :error or higher and output to stderr.

NobbZ

NobbZ

I took the freedom to edit some code fences in.

As this:

some text [ ]

renders into


some text


Where the is a clickable checkbox.

Koszal

Koszal

My goal was not to write to STDERR - rather to have the standard logger behave sensibly. (And I understand my definition of sensible may not match typical BEAM use cases).

Maybe I’ll provide more context:

I am writing a tiny app that will talk to a legacy XML API (a get-to-know Elixir/LiveView project).
I started with the XML API interface. Request payloads are rendered using EEx templates. I liked how I could pattern match to select the appropriate template and then render it injecting required values. Once I had that ready I whipped up an .exs script that reads key value pairs (from System.argv). I could fire it off and render requests to STDOUT. The next step was piping to | curl -d@- -XPOST http://... The server complained about illegal input. After a bit of poking I realized log messages went to STDOUT rather than STDERR so I was feeding not only XML but logger output to the remote host.

And hence my question about having logger write to STDOUT.

dwark

dwark

The whole Logger business is somewhat of Dark Magic to me, but like @hauleth said, it looks like you would need to:

  • filter out level :error for the default_handler (which logs to stdio by default)
  • add a second handler, filter out all but level :error and config it to log to stderr

(assuming the default handler is not logging to file).

Where Next?

Popular in Questions Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
sacepums
Hey guys. I'm new to elixir and im really stocked about it. But I ran into a bit of problem - I need to convert a date sting, for examp...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
Codball
Mix format works fine if run from the cmd. I’ve followed this to facilitate the implementation into VSC which involves downloading an ext...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

Other popular topics Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
Jim
As a follow up to my earlier question: I have the code compiling and running but not getting a successful login from the rest server. ...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list....
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 42633 214
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New

We're in Beta

About us Mission Statement