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

srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
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
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
script
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this "1000" What is the ...
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
Fl4m3Ph03n1x
Background Let’s assume I have a typical GenServer that receives messages as requests, does some operation in a DB and returns responses....
New
kostonstyle
Hi all I want to have a unix time, from the current time plus 1 hour. DateTime.now + 1 hour How to get it in elixir? Thanks
New
hpopp
To simplify some tasks at work, I wrote and published this package yesterday. It’s a simple macro that enables Access behaviour on struct...
New
jc00ke
Expanding on this topic: https://forum.elixirforum.net/t/map-typespec-question/19217 Let’s say I have a map with required and optional k...
New
idi527
I’ve been re-reading swift book again and noticed that multiline strings there don’t have a trailing line break, unlike in elixir iex(2)...
New

Other popular topics Top

Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
977 41022 311
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
New
_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
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
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
Nvim
Elixir appears to be a superior language to Python. I don’t see any advantage of Python over Elixir. Are there any?
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

We're in Beta

About us Mission Statement