如何自定义Elixir Logger的metadata输出格式为模块.函数(行号)样式
Elixir Logger 自定义元数据格式解决方案
默认的Elixir Logger控制台格式器不支持直接通过$metadata[字段名]的语法单独提取单个元数据字段拼接,你可以通过自定义格式函数实现需求,步骤如下:
步骤1:编写自定义格式器
在项目lib/目录下新增自定义格式器模块,比如lib/your_app/logger_formatter.ex:
defmodule YourApp.LoggerFormatter do @moduledoc "自定义日志格式器,实现模块.函数(行号)的元数据展示" def format(level, message, timestamp, metadata) do # 提取目标元数据,不存在时设置默认值避免报错 module = Keyword.get(metadata, :module, "UnknownModule") function = Keyword.get(metadata, :function, "unknown_func/0") line = Keyword.get(metadata, :line, 0) # 拼接自定义格式的元数据字符串 # Module.split 用于去掉模块名默认带的Elixir.前缀 module_name = if is_atom(module), do: module |> Module.split() |> Enum.join("."), else: to_string(module) meta_str = "#{module_name}.#{function}(#{line})" # 最终日志输出格式,可按需调整顺序和样式 "[#{format_timestamp(timestamp)}] [#{level}] #{meta_str}: #{IO.chardata_to_string(message)}\n" end # 保持和默认Logger一致的时间格式 defp format_timestamp({_date, {h, m, s, ms}}) do "#{pad2(h)}:#{pad2(m)}:#{pad2(s)}.#{pad3(ms)}" end defp pad2(num), do: num |> to_string() |> String.pad_leading(2, "0") defp pad3(num), do: num |> to_string() |> String.pad_leading(3, "0") end
步骤2:修改Logger配置
更新config.exs中的Logger配置,指定使用自定义的格式函数:
config :logger, :console, metadata: [:module, :function, :line], format: {YourApp.LoggerFormatter, :format}, # 可选:设置日志级别、颜色等其他配置 level: :debug
简化版本(无需自己处理时间/级别格式)
如果你只需要修改元数据的展示样式,其他部分保留Logger默认格式,可以简化格式器实现:
def format(level, message, timestamp, metadata) do module = Keyword.get(metadata, :module, "UnknownModule") function = Keyword.get(metadata, :function, "unknown_func/0") line = Keyword.get(metadata, :line, 0) module_name = if is_atom(module), do: module |> Module.split() |> Enum.join("."), else: to_string(module) custom_meta = "#{module_name}.#{function}(#{line})" # 复用默认格式模板,只替换元数据部分 format_template = Logger.Formatter.compile("[$time] [$level] $metadata: $message\n") Logger.Formatter.format(format_template, level, message, timestamp, metadata: custom_meta) end
内容的提问来源于stack exchange,提问作者Code Wiget
相关产品推荐
相关产品推荐

