Current section
Files
Jump to
Current section
Files
lib/logger/default.ex
defmodule Argos.Logger.Default do
@moduledoc """
Implementación por defecto del logger de Argos.
Usa Aurora para colorear el mensaje según el nivel y aplicar efectos.
"""
@behaviour Argos.Logger.Behaviour
alias Aurora.{Color, Effects, Format}
alias Aurora.Structs.{ChunkText, EffectInfo}
@effects %{
debug: [:dim],
info: [],
warning: [:bold],
error: [:bold],
critical: [:bold, :blink],
emergency: [:bold, :blink, :reverse],
alert: [:bold, :blink]
}
@impl Argos.Logger.Behaviour
def log(level, message, metadata) do
effects = Map.get(@effects, level, [])
level
|> format_message(message, metadata, effects)
|> IO.puts()
end
defp format_message(level, message, metadata, effects) do
timestamp = format_timestamp(metadata[:timestamp])
level_str = String.upcase(to_string(level))
module_info = format_module(metadata)
chunks = build_log_chunks(timestamp, level, level_str, module_info, message, effects)
Format.format(chunks)
end
defp build_log_chunks(timestamp, level, level_str, module_info, message, effects) do
timestamp_chunks =
if timestamp != "" do
[
%ChunkText{
text: timestamp,
color: Color.to_color_info(:secondary),
effects: %EffectInfo{dim: true}
},
%ChunkText{
text: " ",
color: Color.to_color_info(:no_color)
}
]
else
[]
end
level_chunks = [
%ChunkText{
text: "[#{level_str}]",
color: Color.to_color_info(level),
effects: Effects.to_effect_info(effects)
},
%ChunkText{
text: " ",
color: Color.to_color_info(:no_color)
}
]
module_chunks =
if module_info != "" do
[
%ChunkText{
text: module_info,
color: Color.to_color_info(:info),
effects: %EffectInfo{dim: true}
}
]
else
[]
end
message_chunks = [
%ChunkText{
text: message,
color: Color.to_color_info(level),
effects: %EffectInfo{}
}
]
Enum.concat([timestamp_chunks, level_chunks, module_chunks, message_chunks])
end
def format_timestamp({{year, month, day}, {hour, min, sec, millisec}}) do
"#{year}-#{pad(month)}-#{pad(day)} #{pad(hour)}:#{pad(min)}:#{pad(sec)}.#{pad(millisec, 3)}"
end
def format_timestamp(_), do: ""
defp pad(number, length \\ 2) do
number
|> Integer.to_string()
|> String.pad_leading(length, "0")
end
def format_module(metadata) do
case {metadata[:module], metadata[:function], metadata[:file], metadata[:line]} do
{mod, fun, file, line}
when not is_nil(mod) and not is_nil(fun) and not is_nil(file) and not is_nil(line) ->
"#{inspect(mod)}.#{fun} #{file}:#{line} "
_ ->
""
end
end
end