1defmodule Logger.BackendSupervisor do 2 @moduledoc false 3 4 use Supervisor 5 @name Logger.BackendSupervisor 6 7 @doc """ 8 Starts the backend supervisor. 9 """ 10 def start_link(_) do 11 case Supervisor.start_link(__MODULE__, [], name: @name) do 12 {:ok, _} = ok -> 13 for backend <- Application.get_env(:logger, :backends) do 14 case watch(backend) do 15 {:ok, _} -> 16 :ok 17 18 {:error, {{:EXIT, exit}, _spec}} -> 19 raise "EXIT when installing backend #{inspect(backend)}: " <> 20 Exception.format_exit(exit) 21 22 {:error, error} -> 23 raise "ERROR when installing backend #{inspect(backend)}: " <> 24 Exception.format_exit(error) 25 end 26 end 27 28 ok 29 30 {:error, _} = error -> 31 error 32 end 33 end 34 35 @doc """ 36 Removes the given `backend`. 37 """ 38 def unwatch(backend) do 39 handler = translate_backend(backend) 40 41 case Supervisor.terminate_child(@name, handler) do 42 :ok -> 43 _ = Supervisor.delete_child(@name, handler) 44 :ok 45 46 {:error, _} = error -> 47 error 48 end 49 end 50 51 @doc """ 52 Watches the given `backend`. 53 """ 54 def watch(backend) do 55 handler = translate_backend(backend) 56 57 spec = %{ 58 id: handler, 59 start: {Logger.Watcher, :start_link, [{handler, backend}]}, 60 restart: :transient 61 } 62 63 case Supervisor.start_child(@name, spec) do 64 {:error, :already_present} -> 65 _ = Supervisor.delete_child(@name, handler) 66 watch(backend) 67 68 other -> 69 other 70 end 71 end 72 73 @doc """ 74 Translates the shortcut backend name into its handler. 75 """ 76 def translate_backend(:console), do: Logger.Backends.Console 77 def translate_backend(other), do: other 78 79 @impl true 80 def init(children) do 81 Supervisor.init(children, strategy: :one_for_one, max_restarts: 30, max_seconds: 3) 82 end 83end 84