查看源代码 Logger.Formatter (Logger v1.16.2)
日志的便利功能和内置格式化程序。
此模块定义了一个合适的 :logger
格式化程序,它将消息和报告格式化为 Elixir 项,并提供其他功能,例如时区转换、截断和着色。此格式化程序是 Logger
的默认格式化程序,您可以使用以下方法配置它:
config :logger, :default_formatter,
format: "\n$time $metadata[$level] $message\n",
metadata: [:user_id]
有关所有配置选项,请参阅 Logger.Formatter.new/1
。
您还可以通过调用 new/1
并设置任何 :logger
处理程序的格式化程序来构建此格式化程序的实例,方法是将其 :formatter
键设置为 Logger.Formatter.new(options)
。
此模块还为希望 编写自定义日志格式化程序 的人提供了几个便利功能。
格式化
日志消息可以通过格式化字符串控制。以下是一个例子:
config :logger, :default_formatter,
format: "\n$time $metadata[$level] $message\n",
metadata: [:user_id]
以上将打印错误消息为:
18:43:12.439 user_id=13 [error] Hello\n
您可以使用的有效参数是
$time
- 发送日志消息的时间$date
- 发送日志消息的日期$message
- 日志消息$level
- 日志级别$node
- 打印消息的节点$metadata
- 以"key=val key2=val2 "
格式呈现的用户控制数据
格式化函数
如果您希望更改消息的格式但保留 Logger.Formatter
提供的所有其他功能(例如截断和着色),您还可以使用 {module, function_name}
元组来自定义日志消息的格式。但是,如果您想完全控制格式化,请考虑编写一个自定义的 :logger
格式化程序,它可以完全访问所有事件和元数据。
使用 {module, function_name}
时,该函数将使用级别、消息、时间戳和元数据调用,如下所示:
defmodule MyConsoleLogger do
@spec format(atom, chardata, Logger.Formatter.date_time_ms(), keyword()) :: IO.chardata()
def format(level, message, timestamp, metadata) do
# Custom formatting logic that must return chardata.
# ...
end
end
元数据
可以使用 Logger.metadata/0
和 Logger.metadata/1
函数读取和写入发送到记录器的元数据。例如,您可以设置 Logger.metadata([user_id: 13])
将 user_id 元数据添加到当前进程。用户可以配置后端以选择要打印的元数据,它将替换 $metadata
值。
总结
类型
@type date() :: {1970..10000, 1..12, 1..31}
@type pattern() :: :date | :level | :levelpad | :message | :metadata | :node | :time
@type time_ms() :: {0..23, 0..59, 0..59, 0..999}
函数
@spec compile(binary() | nil) :: [pattern() | binary()]
@spec compile(pattern) :: pattern when pattern: {module(), function :: atom()}
将模式或函数编译成 format/5
可以处理的数据结构。
查看模块文档以获取有关将在模式中插值的有效参数的文档。如果您将 nil
作为模式传递,则模式默认为:
"\n$time $metadata[$level] $message\n"
如果您想使用自定义函数自定义格式化,则可以传递一个 {module, function_name}
元组。
此函数与 format/5
一起是 Logger.Formatter.new/1
用于格式化消息的主要构建块。那些有兴趣构建自定义格式化程序的人也可以使用它。
示例
iex> Logger.Formatter.compile("$time $metadata [$level] $message\n")
[:time, " ", :metadata, " [", :level, "] ", :message, "\n"]
iex> Logger.Formatter.compile({MyLoggerFormatter, :format})
{MyLoggerFormatter, :format}
@spec format( mod_and_fun | [pattern() | binary()], Logger.level(), Logger.message(), date_time_ms(), keyword() ) :: IO.chardata() when mod_and_fun: {atom(), atom()}
格式化由 compile/1
返回的 pattern_or_function
。
它接受一个已编译的格式,并注入级别、时间戳、消息和元数据关键字列表,并返回一个格式正确的字符串。
如果 pattern_or_function
是一个 {module, function_name}
元组,则调用 module.function_name(level, message, timestamp, metadata)
来获取消息。
此函数与 compile/1
一起是 Logger.Formatter.new/1
用于格式化消息的主要构建块。那些有兴趣构建自定义格式化程序的人也可以使用它。
示例
iex> pattern = Logger.Formatter.compile("[$level] $message")
iex> timestamp = {{1977, 01, 28}, {13, 29, 00, 000}}
iex> formatted = Logger.Formatter.format(pattern, :info, "hello", timestamp, [])
iex> IO.chardata_to_string(formatted)
"[info] hello"
@spec format_date(date()) :: IO.chardata()
将日期格式化为 chardata。
@spec format_event(:logger.log_event(), pos_integer() | :infinity) :: IO.chardata()
格式化日志事件的消息。
@spec format_time(time_ms()) :: IO.chardata()
将时间格式化为 chardata。
为 :logger
处理程序初始化格式化程序。
支持的选项是
:colors
- 着色选项的关键字列表。:format
- 用于打印日志的格式消息。默认为:"\n$time $metadata[$level] $message\n"
。它也可以是一个{module, function_name}
元组,它将使用日志级别、消息、当前时间戳和元数据调用,并且必须返回IO.chardata/0
。有关:format
的更多信息,请参阅模块文档。:metadata
- 由$metadata
打印的元数据。默认为空列表(无元数据)。将:metadata
设置为:all
将打印所有元数据。有关更多信息,请参阅Logger
文档中的“元数据”部分。:truncate
- 要记录的最大消息大小(以字节为单位)。默认为 8192 字节。请注意,此配置是近似值。截断的消息将在末尾添加" (truncated)"
。可以传递原子:infinity
来禁用此行为。:utc_log
- 当true
时,在日志中使用 UTC。默认情况下,它使用本地时间(因为它默认为false
)。
:colors
关键字列表中支持的键是
:enabled
- 布尔值,允许打开和关闭着色。默认为:IO.ANSI.enabled?/0
:debug
- 调试消息的颜色。默认为::cyan
:info
- 信息和通知消息的颜色。默认为::normal
:warning
- 警告消息的颜色。默认为::yellow
:error
- 错误和更高消息的颜色。默认为::red
有关颜色和属性的列表,请参阅 IO.ANSI
模块。消息的颜色也可以通过 :ansi_color
元数据在每条消息中进行配置。
@spec prune(IO.chardata()) :: IO.chardata()
从列表中修剪无效的 Unicode 代码点和无效的 UTF-8 字节。
通常在格式化后调用,此时无法打印数据。
@spec system_time_to_date_time_ms(integer(), boolean()) :: date_time_ms()
将元数据中的系统时间(以微秒为单位)转换为 date_time_ms
元组。
@spec truncate(IO.chardata(), non_neg_integer() | :infinity) :: IO.chardata()
将 chardata
截断为 n
字节。
我们有可能在 grapheme 集群的中间进行截断,但我们绝不会在二进制代码点的中间进行截断。因此,截断并不精确。