非常教程

Elixir 1.5参考手册

登录 | Logger

登录 | Logger

Elixir应用程序的记录器。

它包括许多特点:

  • 提供调试、信息、警告和错误级别。
  • 支持插入时自动监督的多个后端Logger
  • 格式化并截断客户端上的消息以避免堵塞Logger后端。
  • 同步模式和异步模式之间的交替,在需要时保持性能,但在压力下也要施加背压。
  • 包裹OTP error_logger以防止其溢出。记录对于跟踪您的系统中发生感兴趣的事件很有用。例如,每当用户被删除时记录日志会很有帮助.def delete_user(user)do Logger.info fn - >“从系统中删除用户:#{inspect(user)}”end#... end Logger.info/2宏发出所提供的消息在该:info级别。其他级别还有其他宏。

注意

  • Logger.info/2在上面的例子中传递给参数的参数是一个零参数函数Logger宏接受消息作为字符串以及函数,建议在消息计算昂贵时使用函数。在上面的示例中,即使邮件在运行时不会实际记录,也会对邮件进行评估(因此内部插值也是如此),而不管其级别如何。避免评估此类消息的唯一方法是在编译时通过:compile_time_purge_level选项清除日志调用(请参见下文),或者使用仅在消息需要根据运行时级别进行记录时评估才生成消息的函数。等级支持的等级是:
  • :debug-用于与调试相关的消息
  • :info-任何形式的资料
  • :warn-警告
  • :error-错误

配置

Logger支持广泛的配置。

这种配置分为三类:

  • 应用程序配置-必须在:logger应用程序已启动
  • 运行时配置-可以在:logger应用程序已启动,但在运行时可能会更改。
  • 错误记录器配置 - 配置OTP error_logger应用程序配置的包装必须config/config.exs:logger应用程序启动之前通过配置文件(如)设置以下配置。
  • :backends-将使用的后端。默认为[:console]有关更多信息,请参见“后端”部分。
  • :compile_time_purge_level- 在编译时清除日志级别低于此选项值的所有调用。这意味着Logger低于此选项的调用将在编译时被完全删除,在运行时不会产生开销。默认为:debug,只适用于Logger.debug/2Logger.info/2Logger.warn/2,和Logger.error/2宏(例如,它并不适用于Logger.log/3)。请注意,传递给Logger在编译时从AST中移除的调用的参数永远不会被计算,因此在这些参数中发生的任何函数调用都不会执行。因此,如果等于或高于此值,则避免类似于Logger.debug("Cleanup: #{perform_cleanup()}")示例中的代码perform_cleanup/0将不会执行。:compile_time_purge_level:info
  • :compile_time_application- :application在编译时将元数据值设置为配置的值。这种配置通常只可用于构建工具的应用程序自动添加到元数据Logger.debug/2Logger.info/2电话等风格。

例如,若要配置:backendscompile_time_purge_level选项config/config.exs档案:

config :logger,
  backends: [:console],
  compile_time_purge_level: :info

运行时配置

下面的所有配置可以通过配置文件(如config/config.exs)设置,但也可以在运行时通过动态更改Logger.configure/1

  • :level - 日志级别。尝试记录严重程度低于配置级别的任何消息将简单地导致该消息被忽略。请记住,每个后端也可能有其特定的级别。请注意,与:compile_time_purge_level选项不同,传递给Logger调用的参数即使调用级别低于,也会被评估:level。因为这个原因,计算成本很高的消息应该被包装在0-arity匿名函数中,这些函数只有在:label选项需要时才会被评估。
  • :utc_log- 当true,在日志中使用UTC。默认情况下它使用本地时间(即,它默认为false)。
  • :truncate - 要记录的最大消息大小(以字节为单位)。默认为8192字节。注意这个配置是近似的。截断的消息将" (truncated)"在最后。:infinity可以传递原子以禁用此行为。
  • :sync_threshold- 如果Logger管理员:sync_threshold队列中的消息多于消息,Logger则将更改为同步模式,以向客户端应用反压。一旦队列中的消息数量减少为消息,Logger将返回异步模式sync_threshold * 0.75。默认为20条消息。
  • :translator_inspect_opts - 在翻译OTP报告和错误时,必须在错误报告中检查最后的消息和状态。例如,要配置文件中的选项:level:truncate选项config/config.exs:config:logger,level::warn,truncate:4096错误记录器配置以下配置适用于Logger包装器Erlang的error_logger。下面的所有配置必须在:logger应用程序启动之前设置。
  • :handle_otp_reports- 重定向OTP报告,Logger以便以Elixir条款进行格式化。这将卸载Erlang的记录器,该记录器将条款打印到终端。默认为true
  • :handle_sasl_reports- 重定向主管,崩溃和进度报告,Logger以便以Elixir条款格式化。您的应用程序必须保证:sasl在之前启动:logger。这意味着您可能会看到一些使用Erlang语法编写的初始报告,直到Logger应用程序启动并卸载SASL的记录器为止。默认为false
  • :discard_threshold_for_error_logger-一个值,当到达该值时,将触发错误记录器丢弃消息。此值必须是一个正数,表示每秒接受的最大消息数。一旦超过此阈值,error_logger进入丢弃模式的剩余的第二秒钟。默认为500条消息。

例如,要配置Logger重定向error_logger使用config/config.exs档案:

config :logger,
  handle_otp_reports: true,
  handle_sasl_reports: true

此外,Logger允许Erlang发送的消息通过error_logger翻译器翻译成Elixir格式。随时可以使用API add_translator/1remove_translator/1API 动态添加翻译器。检查Logger.Translator更多信息。

Backends

Logger支持写入日志消息的不同后端。

默认情况下,可用后端如下:

  • :console-将消息记录到默认启用的控制台%28中开发人员也可以实现他们自己的后端,下面将更详细地讨论这个选项。初始后端通过:backends配置,必须在:logger应用程序已启动。控制台后端控制台后端通过将消息打印到控制台来记录消息。它支持以下选项:
  • :level-此后端要记录的级别。注意,消息是由普通程序过滤的。:level控件的配置。:logger先申请。
  • :format-用于打印日志的格式消息。默认为:"\n$time $metadata[$level] $levelpad$message\n"也可能是{module, function}使用日志级别、消息、当前时间戳和元数据调用的元组。
  • :metadata- 要打印的元数据$metadata。默认为空列表(无元数据)。设置:metadata:all打印所有元数据。
  • :colors-着色选项的关键字列表。
  • :device - 将错误消息记录到的设备。默认为,:user但可以更改为其他内容,例如:standard_error
  • :max_buffer - 等待IO设备确认时缓冲的最大事件(默认值:32)。一旦缓冲区满了,后台将阻塞,直到收到确认。除了用户提供的密钥Logger.metadata/1,以下额外的密钥可用于:metadata列表:
  • :application-目前的申请
  • :module-目前的模块
  • :function-目前的职能
  • :file-当前档案
  • :line-当前线路
  • :pid-当前进程ID控件中支持的键。:colors关键字列表是:
  • :enabled - 允许打开和关闭着色的布尔值。默认为:IO.ANSI.enabled?/0
  • :debug-调试消息的颜色。默认为::cyan
  • :info-信息信息的颜色。默认为::normal
  • :warn-警告信息的颜色。默认为::yellow
  • :error-错误信息的颜色。默认为::red

IO.ANSI模块,以获取颜色和属性列表。

下面是如何配置:console后端config/config.exs档案:

config :logger, :console,
  format: "\n$time $metadata[$level] $levelpad$message\n",
  metadata: [:user_id]

自定义格式

控制台后端允许您使用:format选择。

你可以:format到字符串或{module, function}如果您希望提供您自己的格式函数,请使用元组。大{module, function}将使用日志级别、消息、当前时间戳和元数据调用。

下面是如何配置:console后端config/config.exs档案:

config :logger, :console,
  format: {MyConsoleLogger, :format}

下面是一个如何定义MyConsoleLogger.format/4从上面的配置。

defmodule MyConsoleLogger do
  def format(level, message, timestamp, metadata) do
    # Custom formatting logic...
  end
end

你可以阅读更多关于格式化的内容Logger.Formatter

自定义后端

任何开发人员都可以创建自己的Logger后端。自Logger是一个事件管理器:gen_event,编写新后端是创建事件处理程序的问题,如:gen_event文件。

从现在开始,我们将使用术语“事件处理程序”来引用您的自定义后端,同时我们将深入了解实现细节。

一旦:logger应用程序启动时,它会安装下面列出的所有事件处理程序:backends配置到Logger事件管理器。事件管理器和所有添加的事件处理程序将自动受到监控Logger

初始化后,处理程序应设计为以下列格式处理事件:

{level, group_leader, {Logger, message, timestamp, metadata}} | :flush

其中:

  • level是以下之一:debug:info:warn,或:error,如先前所描述
  • group_leader是记录消息的进程的组长。
  • {Logger, message, timestamp, metadata}包含有关日志消息的信息的元组:
- the first element is always the atom [`Logger`](logger#content) 
-  `message` is the actual message (as chardata) 
-  `timestamp` is the timestamp for when the message was logged, as a `{{year, month, day}, {hour, minute, second, millisecond}}` tuple 
-  `metadata` is a keyword list of metadata used when logging the message 

建议处理程序忽略组领导位于与安装处理程序不同的节点中的消息。例如:

def handle_event({_level, gl, {Logger, _, _, _}}, state)
    when node(gl) != node() do
  {:ok, state}
end

在事件的情况下:flush处理程序应该刷新所有挂起的数据。此事件由flush/0...

此外,后端可以通过configure_backend/2函数,它要求事件处理程序处理以下格式的调用:

{:configure, options}

哪里options是关键字列表。调用的结果是返回的结果configure_backend/2。推荐的成功配置返回值是:ok

建议后端至少支持以下配置选项:

  • :level-该后端的日志记录级别
  • :format-该后端的日志格式
  • :metadata-要包含在后端的元数据

检查实现Logger.Backends.Console,例如如何处理本节中的建议以及如何处理现有的选项。

类型

backend()level()message()metadata()

函数

add_backend(backend, opts \ [])

添加一个新后端

add_translator(translator)

增加一个新的翻译

bare_log(level, chardata_or_fun, metadata \ [])

动态记录消息

compare_levels(level, level)

比较日志级别

configure(options)

配置记录器

configure_backend(backend, options)

配置给定的后端。

debug(chardata_or_fun, metadata \ [])

记录调试消息

disable(pid)

禁用当前进程的日志记录。

enable(pid)

启用当前进程的日志记录。

error(chardata_or_fun, metadata \ [])

记录错误消息

flush()

冲记录器

info(chardata_or_fun, metadata \ [])

记录一条信息消息

level()

检索Logger关卡

log(level, chardata_or_fun, metadata \ [])

将消息记录到给定的level

metadata()

读取当前进程元数据。

metadata(keyword)

根据给定的关键字列表更改当前进程元数据。

remove_backend(backend, opts \ [])

移除后端

remove_translator(translator)

移除翻译

reset_metadata(keywords \ [])

将当前进程元数据重置为给定的关键字列表。

warn(chardata_or_fun, metadata \ [])

记录警告消息

backend()

backend() :: :gen_event.handler

level()

level() :: :error | :info | :warn | :debug

message()

message() :: IO.chardata | String.Chars.t

metadata()

metadata() :: keyword(String.Chars.t)

add_backend(backend, opts \ [])

add_backend(atom, keyword) :: Supervisor.on_start_child

添加一个新后端。

备选方案

  • :flush-何时true,保证当前发送给Logger和Erlang的所有消息error_logger在添加后端之前进行处理。加[医]翻译%28翻译%29add_translator({module, function :: atom}) :: :ok增加了一个新的翻译。裸露[医]日志%28,字符[医]或[医]有趣,元数据[医][]%29bare_log(level, message | (() -> message | {message, keyword}), keyword) :: :ok | {:error, :noproc} | {:error, term}动态记录消息。只有在需要显式避免嵌入元数据时才使用此函数。比较[医]级别%28,级别%29compare_levels(level, level) :: :lt | :eq | :gt比较日志级别。接收两个日志级别并比较left相对于right级别和回报
  • :lt如果left小于right
  • :eq如果leftright是平等的
  • :gt如果left大于right

实例

iex> Logger.compare_levels(:debug, :warn)
:lt
iex> Logger.compare_levels(:error, :info)
:gt

configure(options)

configure(keyword) :: :ok

配置记录器。

有关Logger可用选项,请参阅模块文档中的“运行时配置”部分。

configure_backend(backend, options)

configure_backend(backend, keyword) :: term

配置给定的后端。

后端需要启动并运行,以便在运行时进行配置。

debug(chardata_or_fun, metadata \ []) (macro)

记录调试消息。

返回:ok或一个{:error, reason}元组。

实例

Logger.debug "hello?"
Logger.debug fn -> "expensive to calculate debug" end
Logger.debug fn -> {"expensive to calculate debug", [additional: :metadata]} end

disable(pid)

disable(pid) :: :ok

禁用当前进程的日志记录。

目前唯一可接受的PID是self()

enable(pid)

enable(pid) :: :ok

启用当前进程的日志记录。

目前唯一可接受的PID是self()

error(chardata_or_fun, metadata \ []) (macro)

记录错误消息。

返回:ok或一个{:error, reason}元组。

实例

Logger.error "oops"
Logger.error fn -> "expensive to calculate error" end
Logger.error fn -> {"expensive to calculate error", [additional: :metadata]} end

flush()

flush() :: :ok

冲记录器。

这保证了所有发送Logger到此通话之前的消息都将被处理。这对测试非常有用,不应在生产代码中调用它。

info(chardata_or_fun, metadata \ []) (macro)

记录一条信息。

返回:ok或一个{:error, reason}元组。

实例

Logger.info "mission accomplished"
Logger.info fn -> "expensive to calculate info" end
Logger.info fn -> {"expensive to calculate info", [additional: :metadata]} end

level()

level() :: level

检索Logger水平。

Logger水平可以通过改变configure/1

log(level, chardata_or_fun, metadata \ []) (macro)

用给定的日志记录消息level

返回:ok或一个{:error, reason}元组。

debug/2warn/2info/2,和error/2优于该宏,因为它们可以自动消除该呼叫到Logger在编译时如果需要的话(参见该文档alotgether Logger模块)。

metadata()

metadata() :: metadata

读取当前进程元数据。

metadata(keyword)

metadata(metadata) :: :ok

根据给定的关键字列表更改当前进程元数据。

此函数将将给定的关键字列表合并到现有元数据中,但将键设置为nil,这将从元数据中删除该键。

remove_backend(backend, opts \ [])

remove_backend(atom, keyword) :: :ok | {:error, term}

移除后端。

备选方案

  • :flush- 何时true,保证当前发送给记录器和Erlang的所有消息error_logger都在删除后端之前处理

remove_translator(translator)

remove_translator({module, function :: atom}) :: :ok

移除翻译。

reset_metadata(keywords \ [])

reset_metadata(metadata) :: :ok

将当前进程元数据重置为给定的关键字列表。

warn(chardata_or_fun, metadata \ []) (macro)

记录一条警告消息。

返回:ok或一个{:error, reason}元组。

实例

Logger.warn "knob turned too far to the right"
Logger.warn fn -> "expensive to calculate warning" end
Logger.warn fn -> {"expensive to calculate warning", [additional: :metadata]} end

登录 | Logger相关

Elixir 1.5

Elixir 基于 Erlang 虚拟机的函数式、面向并行,是一种较好的编程语言。它以 Erlang 为基础,支持分布式、高容错、实时应用程序的开发。

主页 https://elixir-lang.org/
源码 https://github.com/elixir-lang/elixir
版本 1.5
发布版本 1.5.2