elixir 提供了一些方便的模块属性,可以让我们方便的进行elixir 的扩展(尤其是进行元编程的时候)
比如elixir_agent 就使用到了before_compile以及on_definition ,方便进行trace 的处理
on_definition 的简单使用
- 参考demo
内容来自官方,可以实现输出函数的一些信息
defmodule Hooks do
def on_def(_env, kind, name, args, guards, body) do
IO.puts("Defining #{kind} named #{name} with args:")
IO.inspect(args)
IO.puts("and guards")
IO.inspect(guards)
IO.puts("and body")
IO.puts(Macro.to_string(body))
end
end
defmodule MyModule do
@on_definition {Hooks, :on_def}
def hello(arg) when is_binary(arg) or is_list(arg) do
"Hello" <> to_string(arg)
end
def hello(_) do
:ok
end
end
before_compile 的简单使用
- 参考demo
defmodule MyModule do
@before_compile {Dalong, :__before_compile__}
def hello(arg) when is_binary(arg) or is_list(arg) do
"Hello" <> to_string(arg)
end
def hello(_) do
:ok
end
end
Dalong 模块中__before_compile__ 的定义
defmacro __before_compile__(env) do
IO.puts "Before compilation!"
IO.inspect env
quote do
IO.puts "Before compilation!"
end
end
elixir_agent 的使用
elixir_agent 的使用是自己开发了一个macro,通过use 统一导入,使用如下
defmacro __using__(_args) do
quote do
require NewRelic
require NewRelic.Tracer.Macro
require NewRelic.Tracer.Report
Module.register_attribute(__MODULE__, :nr_tracers, accumulate: true)
Module.register_attribute(__MODULE__, :nr_last_tracer, accumulate: false)
@before_compile NewRelic.Tracer.Macro
@on_definition NewRelic.Tracer.Macro
end
end
说明
elixir 的一些玩法比较有意思,看似缺少一些语言的能力,但是kernel 提供的其他功能,实现起来反而更加灵活强大,以下参考链接中对于上述属性
有完整的介绍可以看看
参考资料
https://hexdocs.pm/elixir/1.14.5/Module.html
https://github.com/newrelic/elixir_agent