1. やりたいこと
Elixirでアプリケーションを実装していて、ロギングをどうするのかな、となりました。
単純にやりたいことは、Logger
で出力する内容を標準出力ではなく、特定のファイルに書き込みたい、ということだけでした。
awesome-elixir#loggingでいいのないかなー、と思ったのですが、最初はシンプルなのがいいな、ということで、以下を利用してみました。
2. 使い方
README.mdにある通り、いたって使い方はシンプルです。
config/config.exs
にロギングしたいパスを通すだけです。
config :logger,
backends: [{LoggerFileBackend, :info},
{LoggerFileBackend, :error}]
config :logger, :info,
path: "/path/to/info.log",
level: :info
config :logger, :error,
path: "/path/to/error.log",
level: :error
3. どう実装されてるのか
ちょっと気になったので覗いてみました。
ポイントは、GenEventを利用して、event_handlerでロギングされた内容をファイル書き込みする、というものでした。
下記抜粋でちょっと割愛しています。
def handle_event({level, _gl, {Logger, msg, ts, md}}, %{level: min_level} = state) do
if is_nil(min_level) or Logger.compare_levels(level, min_level) != :lt do
log_event(level, msg, ts, md, state)
else
{:ok, state}
end
end
# helpers
defp log_event(level, msg, ts, md, %{path: path, io_device: io_device, inode: inode} = state) when is_binary(path) do
if !is_nil(inode) and inode == inode(path) do
IO.write(io_device, format_event(level, msg, ts, md, state))
{:ok, state}
else
File.close(io_device)
log_event(level, msg, ts, md, %{state | io_device: nil, inode: nil})
end
end
GenEventはまだ利用したことがないので、これを機に覚えてみようと思います^^
4. というかElixir本体のLoggerだけではできないんだっけ?
Loggerのドキュメントのと、Loggerのソースコードを見てみたのですが、そういう機能はなさそうに?見えました。
Loggerのドキュメントでは、developperはCustom backends
を作成できるよ、とあるので、GenEvent
でhandleして自前でファイル書き込みとかをすることになるのでしょうか。
と、思いつつもPR, issuesを見てみたら、過去にこの手のPRもあったみたいですが、リジェクトされてますね。。
phoenixを利用したアプリケーション等などではどう実装したりしてるのか探してみようと思います。
ちょっと調査途中で消化不良ですが本日は以上となります。