PJUllrich

PJUllrich

Author of Building Table Views with Phoenix LiveView

I’ve been trying to add a custom logger backend to my application using the now-recommended :logger.add_handler/3 function as suggested to me by @LostKobrakai (on Twitter). I’ve ran into an issue with the config of the handler, which changes between adding the handler and logging the first event. This is my logger:

defmodule Demo.FileLogger do
  def adding_handler(config) do
    IO.inspect(config, label: "Initial")
    {:ok, config}
  end

  def log(event, config) do
    IO.inspect(event, label: "Event")
    IO.inspect(config, label: "Config")

    :ok
  end
end

This is how I add the handler to my application:

# lib/demo/application.ex
  @impl true
  def start(_type, _args) do
    :ok = :logger.add_handler(:file_log, Demo.FileLogger, %{})
    # ...
end

Now, the handler logs the following config in the adding_handler/1 callback:

Initial: %{
  id: :file_log,
  module: Demo.FileLogger,
  level: :all,
  filters: [],
  filter_default: :log,
  formatter: {:logger_formatter, %{}}
}

but once the log/2 callback is executed for the first time, config only contains the following values:

Config: %{
  id: :file_log,
  module: Demo.FileLogger,
  formatter: {:logger_formatter, %{}}
}

Note the missing level, filters, and filter_default fields. This is surprising to me, because in the “old” :gen_event behaviour for logger backends, you’d set a config during the init/1 callback and this config would be passed to every callback thereafter, just like in a GenServer. Why is this different in the :logger backend and what’s the suggested solution to pass on a config map between all callbacks?

I also implemented the changing_config/2 callback to see whether the config is changed somehow, but it never executes between the adding_handler/1 and the log/2 callback.

Showing Posts 1 to 5

cmo

cmo

Doesn’t the config go under a config key?

%{
  config: %{ level: :error, ...}
}
PJUllrich

PJUllrich OP

Author of Building Table Views with Phoenix LiveView

Yes, I think you’re right. At least that’s what worked for me now. It says so in the docs, too:

Handler specific configuration data is inserted by the handler callback itself, in a sub structure associated with the field named config.

From: logger_handler — OTP 29.0.2 (kernel 11.0.2)

However it’s still confusing because e.g. the spec for the config-type contains all these fields and is references both in the adding_handler/1 and log/2 callbacks, but it’s not the same map in these cases. But anyways. Handler-specific configurations should go under the config.config (also a great naming :D) key I presume.

cmo

cmo

I found it pretty confusing when I moved to the new erlang logger setup. I think the docs need some love in this area.

PJUllrich

PJUllrich OP

Author of Building Table Views with Phoenix LiveView

Yeah, I’m currently battling with converting the old Logger.Formatter.format/5 to :logger_formatter.format/2. Especially converting the old format strings like "$date $time [$level] $message to the new form [:date, " ", :time, " [", :level, "] ", :msg, "\n"] is non-trivial. I appreciate the effort of consolidating the two logging interfaces, but when it comes to extensibility, I’m afraid this is a step backwards.

PJUllrich

PJUllrich OP

Author of Building Table Views with Phoenix LiveView

I managed to write a little helper function that’d convert the old format string to the new template-option format: run-elixir/assets/archived_code/file_logger.ex at 85dd2599d9185c259c03f1226912b48e62e73e8c · PJUllrich/run-elixir · GitHub

— All posts loaded —

Where Next? Top

Trending in Questions Top

katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
achenet
Hello, I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind. However, when I launch mix phx.server, I get an error...
New
kpanic
Hi everyone, I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding. I sta...
New
asweet-confluent
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New
Cxx-mlr
I’m working on a small exercise involving update_in/3, and I came up with this solution: data = %{ name: "Periodic Table", category:...
New
ChrisAmelia
I’ve got trouble wrapping my head around the order in which functions are called in this snippet (from Phoenix’s authentication): toke...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews