text: defmodule Logger.Watcher do
    @moduledoc false
  
    require Logger
    use GenServer
  
    @doc """
    Starts a watcher server.
  
    This is useful when there is a need to start a handler
    outside of the handler supervision tree.
    """
    def start_link(tuple) do
      GenServer.start_link(__MODULE__, tuple)
    end
  
    ## Callbacks
  
    @doc false
    def init({handler, args}) do
      Process.flag(:trap_exit, true)
  
      case :gen_event.delete_handler(Logger, handler, :ok) do
        {:error, :module_not_found} ->
          case :gen_event.add_sup_handler(Logger, handler, args) do
            :ok ->
              {:ok, handler}
  
            {:error, :ignore} ->
              # Can't return :ignore as a transient child under a one_for_one.
              # Instead return ok and then immediately exit normally - using a fake
              # message.
              send(self(), {:gen_event_EXIT, handler, :normal})
              {:ok, handler}
  
            {:error, reason} ->
              {:stop, reason}
  
            {:EXIT, _} = exit ->
              {:stop, exit}
          end
  
        _ ->
          init({handler, args})
      end
    end
  
    @doc false
    def handle_info({:gen_event_EXIT, handler, reason}, handler)
        when reason in [:normal, :shutdown] do
      {:stop, reason, handler}
    end
  
    def handle_info({:gen_event_EXIT, handler, reason}, handler) do
      message = [
        ":gen_event handler ",
        inspect(handler),
        " installed in Logger terminating\n",
        "** (exit) ",
        format_exit(reason)
      ]
  
      cond do
        logger_has_backends?() -> :ok
        true -> IO.puts(:stderr, message)
      end
  
      {:stop, reason, handler}
    end
  
    def handle_info(_msg, state) do
      {:noreply, state}
    end
  
    defp logger_has_backends?() do
      try do
        :gen_event.which_handlers(Logger) != [Logger.Config]
      catch
        _, _ -> false
      end
    end
  
    def terminate(_reason, handler) do
      # On terminate we remove the handler, this makes the
      # process sync, allowing existing messages to be flushed
      :gen_event.delete_handler(Logger, handler, :ok)
      :ok
    end
  
    defp format_exit({:EXIT, reason}), do: Exception.format_exit(reason)
    defp format_exit(reason), do: Exception.format_exit(reason)
  end
  