Skip to content
Permalink
master
Switch branches/tags
Go to file
 
 
Cannot retrieve contributors at this time
92 lines (74 sloc) 2.14 KB
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