2016-10-23 5 views
3

Пришло время использовать Logger в одном из моих приложений сегодня и помнил, что I needed to call require Logger first. Поэтому я решил посмотреть на Logger source code, чтобы узнать, почему debug, info, error и т. Д. - это макросы, а не простые функции.Почему Elixir Logger состоит из макросов?

Из кода макросы для debug, info и т. Д. (И даже их основные функции) выглядят очень просто. Невозможно было просто экспортировать их как методы вместо макросов?


Из кода Logger:

defmacro log(level, chardata_or_fn, metadata \\ []) do 
    macro_log(level, chardata_or_fn, metadata, __CALLER__) 
    end 

    defp macro_log(level, data, metadata, caller) do 
    %{module: module, function: fun, file: file, line: line} = caller 

    caller = 
     compile_time_application ++ 
     [module: module, function: form_fa(fun), file: file, line: line] 

    quote do 
     Logger.bare_log(unquote(level), unquote(data), unquote(caller) ++ unquote(metadata)) 
    end 
end 

Из того, что я могу видеть, это было бы просто проще сделать их в функции вместо макросов.

ответ

4

Это, вероятно, из-за специальной формы __CALLER__, которая предоставляет информацию о вызывающем контексте, включая файл и строку, но доступна только в макросах.

+0

Да, перебирая '__CALLER__' документы, что делает смысл. Я просто предположил, что это похоже на '__DIR__' и можно получить доступ в любом месте. – Sheharyar

+2

Также макросы позволяют вам скомпилировать с запрошенным уровнем журнала. При компиляции с log level 'error' все вызовы для отладочных журналов полностью удаляются из скомпилированного файла. Нет «если log_level> что-то», что делает его очень быстрым. – tkowal

2

Оказывается, еще одна причина заключается в том, что вызывающий код может быть удален во время компиляции для уровней ведения журнала, которые приложение не хочет.

От ElixirForum discussion:

Это позволить код просто полностью не существует для уровней протоколирования, что вы не хотите, так что код никогда даже не называют и не приводит к скорости штрафа, таким образом, вы только заплатите за уровни регистрации, которые вы активно регистрируете.

и

Это так весь вызов Logger может быть удален из кода во время компиляции, если вы используете :compile_time_purge_level