defmodule Kameleoon.Logger do
@moduledoc """
Logger configuration for messages emitted by the native Kameleoon Core.
The logger is global because the underlying Rust Core logger is global.
"""
alias Kameleoon.Native.Events
alias Kameleoon.Native.Nif
@type level :: :none | :error | :warning | :info | :debug
@type logger :: module()
@callback log(level(), String.t()) :: any()
@levels %{
none: 0,
error: 1,
warning: 2,
info: 3,
debug: 4
}
@doc """
Sets the minimum log level emitted by the native Core.
Defaults to `:warning`.
"""
@spec set_log_level(level()) :: :ok
def set_log_level(level) do
Nif.logger_set_log_level(native_level!(level))
end
@doc """
Routes native Core logs to a custom logger.
The logger must be a module implementing `c:log/2`. Pass `nil` to reset
logging back to the Core default logger.
"""
@spec set_logger(logger() | nil) :: :ok | {:error, Kameleoon.Error.t()}
def set_logger(nil) do
with {:ok, _pid} <- Events.set_logger(nil) do
Nif.logger_set_handler(nil)
end
end
def set_logger(logger) when is_atom(logger) do
unless function_exported?(logger, :log, 2) do
raise ArgumentError, "logger module must export log/2"
end
with {:ok, pid} <- Events.set_logger(logger) do
Nif.logger_set_handler(pid)
end
end
def set_logger(_logger) do
raise ArgumentError, "logger must be nil or a module with log/2"
end
defp native_level!(level) do
Map.fetch!(@levels, level)
rescue
KeyError ->
raise ArgumentError,
"invalid log level #{inspect(level)}, expected one of #{inspect(Map.keys(@levels))}"
end
end