defmodule Phoenix.LiveDashboard.LoggerPubSubBackend do @moduledoc false # Erlang/OTP log handler def log(%{meta: metadata, level: level} = event, config) do with {pubsub, topic} <- metadata[:logger_pubsub_backend] do %{formatter: {formatter_mod, formatter_config}} = config chardata = formatter_mod.format(event, formatter_config) Phoenix.PubSub.broadcast(pubsub, topic, {:logger, level, chardata}) end end @behaviour :gen_event @impl true def init(_) do config = Application.get_env(:logger, :console) format = Logger.Formatter.compile(Keyword.get(config, :format)) metadata = Keyword.get(config, :metadata, []) |> configure_metadata() {:ok, {format, metadata}} end @impl true def handle_call({:configure, _options}, state) do {:ok, :ok, state} end @impl true def handle_event({level, gl, {Logger, msg, ts, metadata}}, {format, keys} = state) when node(gl) == node() do with {pubsub, topic} <- metadata[:logger_pubsub_backend] do metadata = take_metadata(metadata, keys) formatted = Logger.Formatter.format(format, level, msg, ts, metadata) Phoenix.PubSub.broadcast(pubsub, topic, {:logger, level, formatted}) end {:ok, state} end def handle_event(_, state) do {:ok, state} end @impl true def handle_info(_, state) do {:ok, state} end defp configure_metadata(:all), do: :all defp configure_metadata(metadata), do: Enum.reverse(metadata) defp take_metadata(metadata, :all) do metadata end defp take_metadata(metadata, keys) do Enum.reduce(keys, [], fn key, acc -> case Keyword.fetch(metadata, key) do {:ok, val} -> [{key, val} | acc] :error -> acc end end) end end