我可以自动在所有模块中使用Logger吗?

时间:2018-01-10 02:28:11

标签: elixir

在我的大多数模块中,我

require Logger

然后做一些日志记录。在我不熟悉的模块中,我经常进行更改,包括添加一些日志记录,然后我必须使用记录器标记我。

每个模块中require记录器的成本是多少?有没有一种干净的方法可以永远require Logger而不在每个模块中提及它?

2 个答案:

答案 0 :(得分:7)

require的主要目的是提供对所需模块中声明的的访问权限:

  

模块中的公共功能是全局可用的,但是为了使用宏,您需要通过要求定义它们的模块来选择加入。
   - 来自Kernel.SpecialForms.require/2

的文档

此外,来自Elixir guide

  

宏是词汇:无法全局注入代码或宏。要使用宏,您需要明确要求或导入定义宏的模块。

重点是我的。这样做是为了您自己的安全:与函数不同,宏可能会彻底修改您现有的AST。 Logger是此行为的一个完美示例:当级别小于config中指定的相应compile_time_purge_level时,它不会在AST中留下任何痕迹。没有单一的noop。没有。虚无。

这就是为什么Logger被实现为宏的原因。

有两种方法可以克服这种行为。

<强> 1。简单。不推荐。

Logger作为一个函数

创建自己的包装器
defmodule Log do 
  require Logger
  def log(whatever), do: Logger.log(whatever)
end

Log.log现在随处可用(因为它是功能。)

缺点:

  • 在制作中,noop级别的代码中会留下Log.logdebug次来电。这可能会影响表现。
  • 元数据Logger必须是宏的另一个原因)将变得无用 - 你无法获取日志行的行号,模块等因为它们将永远给宏观调用的网站(信用@NathanielWaisbrot)

<强> 2。正确。推荐使用。

创建自己的MyApp.Utils模块,但在每个项目中都存在比todo-or-tictactoe-exercise略复杂的模块。在此模块中,保存所有实用程序功能等,实现宏回调__using__

defmodule MyApp.Utils do
  defmacro __using__(opts \\ []) do
    quote do
      require Logger
      require MyApp.Utils # if this module has macros itself

      def helper, do: Logger.log("Hey, I am always included")
      ...
    end

    ...
  end
end

是的,现在在使用Logger的所有模块中,您必须明确use MyApp.Utils,但由于它包含在应用程序范围内使用的方便帮助程序,因此Logger本身是必需的。免费。

答案 1 :(得分:0)

模块不会从&#34; base&#34;继承。模块。没有继承权。将每个模块视为一个独立的工作单元。

因此,每个模块都应该导入它完成工作所需的所有依赖项。因此,需要在需要进行日志记录的模块中使用Logger是明确的。