More Related Content Similar to Elixir Meetup #1 Loggerの構造と拡張 (20) Elixir Meetup #1 Loggerの構造と拡張15. Supervision Tree
[worker(GenEvent, [[name: Logger]]),
worker(Logger.Watcher, [Logger, Logger.Config, []],
[id: Logger.Config, function: :watcher]),
supervisor(Logger.Watcher, [Logger.Config, :handlers, []]),
worker(Logger.Watcher,
[:error_logger, Logger.ErrorHandler,
{otp_reports?, sasl_reports?, threshold}, :link],
[id: Logger.ErrorHandler, function: :watcher])]
18. Logger.Watcher
# mod: GenEvent(Logger)
def init({mod, handler, args, :monitor}) do
ref = Process.monitor(mod)
res = GenEvent.add_mon_handler(mod, handler, args)
do_init(res, mod, handler, ref)
end
def init({mod, handler, args, :link}) do
res = :gen_event.add_sup_handler(mod, handler, args)
do_init(res, mod, handler, nil)
end
23. Logger.Config
:sync_threshold - if the Logger manager has more than
sync_threshold messages in its queue, Logger will change to sync
mode, to apply backpressure to the clients.
• ログメッセージのイベントを受信
• → メッセージキューの長さをみて動的に同期・非同期を変更
31. OTPのエラーハンドリング
結果として
• handle_otp_reports: true
• ErrorHandler: ログ出力あり (state: otp: trueのため)
• error_logger: ログ出力なし (ハンドラが削除されているため)
• handle_otp_reports: false
• ErrorHandler: ログ出力なし (state: otp: falseのため)
• error_logger: ログ出力あり (ハンドラがそのままのため)
32. OTPエラー出力の抑止
config :logger, handle_otp_reports: false
# 手動でerror_loggerからハンドラを削除
:error_logger.delete_report_handler(:error_logger_tty_h)
# mariaex: v0.4.3
_pid = case Mariaex.Connection.start_link(username: "ecto", database: "ecto_test") do
{:ok, pid} -> pid
{:error, err} ->
IO.puts err.mariadb.message
exit(1)
end
33. おまけ: 雑カスタムBackend
defmodule MyBackend do
use GenEvent
def init(__MODULE__) do
init({:user, []})
end
def init({device, _opts}) do
config = Application.get_env(:logger, :my_backend, [])
format = Keyword.get(config, :format) |> Logger.Formatter.compile
level = Keyword.get(config, :level, :info)
metadata = Keyword.get(config, :metadata, [])
{:ok, %{format: format, metadata: metadata,
level: level, colors: %{}, device: device}}
end
34. おまけ: 雑カスタムBackend
def handle_call({:configure, _options}, state) do
{:ok, :ok, state}
end
def handle_event({_level, gl, _event}, state)
when node(gl) != node() do
{:ok, state}
end
def handle_event({level, _gl, {Logger, msg, _ts, _md}}, state) do
IO.inspect [level, msg]
{:ok, state}
end
end