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