Skip to content

Commit 8647661

Browse files
committed
Fix logger to keep config through config_change/3
Store deleted handlers and live config data in ETS table
1 parent 860b3cc commit 8647661

File tree

3 files changed

+86
-33
lines changed

3 files changed

+86
-33
lines changed

lib/logger/lib/logger/app.ex

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,49 +21,59 @@ defmodule Logger.App do
2121
{otp_reports?, sasl_reports?, threshold}, :link],
2222
[id: Logger.ErrorHandler, function: :watcher])]
2323

24+
config = Logger.Config.new()
25+
2426
case Supervisor.start_link(children, options) do
25-
{:ok, _} = ok ->
26-
deleted = delete_error_logger_handler(otp_reports?, :error_logger_tty_h, [])
27-
deleted = delete_error_logger_handler(sasl_reports?, :sasl_report_tty_h, deleted)
28-
store_deleted_handlers(deleted)
29-
ok
27+
{:ok, sup} ->
28+
handlers = [error_logger_tty_h: otp_reports?,
29+
sasl_logger_tty_h: sasl_reports?]
30+
delete_handlers(handlers)
31+
{:ok, sup, config}
3032
{:error, _} = error ->
33+
Logger.Config.delete(config)
3134
error
3235
end
3336
end
3437

3538
@doc false
36-
def stop(_) do
37-
Application.get_env(:logger, :deleted_handlers)
38-
|> Enum.each(&:error_logger.add_report_handler/1)
39-
40-
# We need to do this in another process as the Application
41-
# Controller is currently blocked shutting down this app.
42-
spawn_link(fn -> Logger.Config.clear_data end)
39+
def stop(config) do
40+
Logger.Config.deleted_handlers()
41+
|> add_handlers()
42+
Logger.Config.delete(config)
43+
end
4344

44-
:ok
45+
@doc false
46+
def config_change(_changed, _new, _removed) do
47+
Logger.Config.configure([])
4548
end
4649

4750
@doc """
4851
Stops the application without sending messages to error logger.
4952
"""
5053
def stop() do
51-
set = Application.get_env(:logger, :deleted_handlers)
52-
Application.put_env(:logger, :deleted_handlers, HashSet.new)
53-
_ = Application.stop(:logger)
54-
Enum.each(set, &:error_logger.add_report_handler/1)
54+
try do
55+
Logger.Config.deleted_handlers([])
56+
catch
57+
:exit, {:noproc, _} ->
58+
{:error, {:not_started, :logger}}
59+
else
60+
deleted_handlers ->
61+
result = Application.stop(:logger)
62+
add_handlers(deleted_handlers)
63+
result
64+
end
5565
end
5666

57-
defp store_deleted_handlers(list) do
58-
Application.put_env(:logger, :deleted_handlers, Enum.into(list, HashSet.new))
67+
defp delete_handlers(handlers) do
68+
deleted? = fn({handler, delete?}) ->
69+
delete? && :error_logger.delete_report_handler(handler) != {:error, :module_not_found}
70+
end
71+
[] = Enum.filter_map(handlers, deleted?, fn({handler, _}) -> handler end)
72+
|> Logger.Config.deleted_handlers()
73+
:ok
5974
end
6075

61-
defp delete_error_logger_handler(should_delete?, handler, deleted) do
62-
if should_delete? and
63-
:error_logger.delete_report_handler(handler) != {:error, :module_not_found} do
64-
[handler|deleted]
65-
else
66-
deleted
67-
end
76+
defp add_handlers(handlers) do
77+
Enum.each(handlers, &:error_logger.add_report_handler/1)
6878
end
6979
end

lib/logger/lib/logger/config.ex

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ defmodule Logger.Config do
44
use GenEvent
55

66
@name __MODULE__
7+
@table __MODULE__
78
@data :__data__
9+
@deleted_handlers :__deleted_handlers__
810

911
def start_link do
1012
GenServer.start_link(__MODULE__, :ok, name: @name)
@@ -44,22 +46,46 @@ defmodule Logger.Config do
4446
def translate_backend(other), do: other
4547

4648
def __data__() do
47-
if data = Application.get_env(:logger, @data) do
48-
data
49+
try do
50+
:ets.lookup_element(@table, @data, 2)
51+
rescue
52+
ArgumentError ->
53+
raise "Cannot use Logger, the :logger application is not running"
4954
else
50-
raise "Cannot use Logger, the :logger application is not running"
55+
nil ->
56+
raise "Cannot use Logger, the :logger application is not running"
57+
data ->
58+
data
5159
end
5260
end
5361

54-
def clear_data() do
55-
Application.delete_env(:logger, @data)
62+
def deleted_handlers() do
63+
try do
64+
:ets.lookup_element(@table, @deleted_handlers, 2)
65+
rescue
66+
ArgumentError ->
67+
[]
68+
end
69+
end
70+
71+
def deleted_handlers(handlers) do
72+
GenEvent.call(Logger, @name, {:deleted_handlers, handlers})
73+
end
74+
75+
def new() do
76+
tab = :ets.new(@table, [:named_table, :public, {:read_concurrency, true}])
77+
true = :ets.insert_new(@table, [{@data, nil}, {@deleted_handlers, []}])
78+
tab
5679
end
5780

81+
def delete(@table) do
82+
:ets.delete(@table)
83+
end
5884
## Callbacks
5985

6086
def init(_) do
6187
# Use previous data if available in case this handler crashed.
62-
state = Application.get_env(:logger, @data) || compute_state(:async)
88+
state = :ets.lookup_element(@table, @data, 2) || compute_state(:async)
6389
{:ok, state}
6490
end
6591

@@ -111,6 +137,12 @@ defmodule Logger.Config do
111137
{:ok, :ok, state}
112138
end
113139

140+
def handle_call({:deleted_handlers, new}, state) do
141+
old = deleted_handlers()
142+
true = :ets.update_element(@table, @deleted_handlers, {2, new})
143+
{:ok, old, state}
144+
end
145+
114146
## Helpers
115147

116148
defp compute_mode(state) do
@@ -159,7 +191,7 @@ defmodule Logger.Config do
159191
end
160192

161193
defp persist(state) do
162-
Application.put_env(:logger, @data, state)
194+
:ets.update_element(@table, @data, {2, state})
163195
state
164196
end
165197
end

lib/logger/test/logger_test.exs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,4 +234,15 @@ defmodule LoggerTest do
234234
wait_for_handler(Logger, Logger.Config)
235235
wait_for_handler(:error_logger, Logger.ErrorHandler)
236236
end
237+
238+
test "Logger.Config updates config on config_change/3" do
239+
:ok = Logger.configure([level: :debug])
240+
try do
241+
Application.put_env(:logger, :level, :error)
242+
assert Logger.App.config_change([level: :error], [], []) === :ok
243+
assert Logger.level() === :error
244+
after
245+
Logger.configure([level: :debug])
246+
end
247+
end
237248
end

0 commit comments

Comments
 (0)