How can I see log metadata in dev?

Just did the same and it worked. I am getting serious now and stopping to just screw around and will find what in our bespoke config loading is causing this. It’ll likely be as simple as just putting Application.put_env(:our_app, :logger) but let’s see.

How does your payload look like? It seems like console logger ignores complex data structures.

config :logger,
  default_formatter: [
    format: "$metadata[$level] $message\n",
    metadata: [:request_id, :primitive, :complex]
  ]
iex> require Logger
Logger
iex> Logger.error("message", primitive: :foo, complex: %{foo: :bar})
primitive=foo [error] message
iex> Logger.error("message", primitive: :foo, complex: :bar)
primitive=foo complex=bar [error] message
iex> Logger.error("message", primitive: :foo, complex: Jason.encode!(%{foo: :bar}))
primitive=foo complex={"foo":"bar"} [error] message
3 Likes

It’s a map.

…and OMFG, you are right. Worked with a string, and it worked when I Jason.encode!-d it (and also when I inspect()-ed it as well).

So to summarize, just having this in your application.ex:

:logger.update_formatter_config(:default, %{metadata: [:your_metadata_key]})

…is enough. You don’t have to touch any of the configs in the config/ directory at all.

And you can just do this after:

Logger.info("stuff", your_metadata_key: other_stuff)

And it will be shown.

And when your metadata is not a primitive value (let’s not argue if string is a primitive, please :smiley:) then you should either JSON encode it, or just inspect it (which turns it into a string that you can just paste in iex most of the time).

So yeah, that’s that. Huge thanks to @LostKobrakai and @ibarch.


I have to say that I am disappointed. This is an implicit behavior that I expected to at least have Logger complain about. It instead silently rejects stuff. :confused: I believe there’s a niche to be served in the Elixir ecosystem by custom Logger formatters, and probably an even bigger niche to just be able to configure Logger on maximum two places (compile + boot time config, and runtime config) and have zero surprises – which must include complaints if you pass it objects it would otherwise ignore.

Writing this down as one of my Elixir grievances. Might be able to tackle it OneDay™.

Yeah, Logger has some sharp edges, but I also believe this might not be the right tool for the job, I’m a big fan of telemetry for these kind of things, even thought structured logs has come to the BEAM, seams like a lot of setup for something that should be simpler, but there might be good reasons for it.

1 Like

Same here for OTel, that’s going to be my next step, I even experimented with OpenObserve in my Golang and Rust work and it worked amazingly well there – logs, metrics and telemetry, all included – so I’ll do it with Elixir next.

Indeed Logger itself seems like it’s not getting the love it deserves and to me it looks more like a thin wrapper over Erlang’s :logger that does not attempt to fix its sharp edges and just carries them over.

Which is fine but it’s IMO dooming it to obscurity.

Good reasons or not, technology should be ergonomic. If it’s not then it’s not living up to its potential. And I quite agree with your “a lot of setup for something that should be simpler”, yep.

1 Like