zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

lazy_logging.ex (3022B)


      1 defmodule Credo.Check.Warning.LazyLogging do
      2   use Credo.Check,
      3     base_priority: :high,
      4     elixir_version: "< 1.7.0",
      5     param_defaults: [
      6       ignore: [:error, :warn, :info]
      7     ],
      8     explanations: [
      9       check: """
     10       Ensures laziness of Logger calls.
     11 
     12       You will want to wrap expensive logger calls into a zero argument
     13       function (`fn -> "string that gets logged" end`).
     14 
     15       Example:
     16 
     17           # preferred
     18 
     19           Logger.debug fn ->
     20             "This happened: \#{expensive_calculation(arg1, arg2)}"
     21           end
     22 
     23           # NOT preferred
     24           # the interpolation is executed whether or not the info is logged
     25 
     26           Logger.debug "This happened: \#{expensive_calculation(arg1, arg2)}"
     27       """,
     28       params: [
     29         ignore: "Do not raise an issue for these Logger calls."
     30       ]
     31     ]
     32 
     33   @logger_functions [:debug, :info, :warn, :error]
     34 
     35   @doc false
     36   @impl true
     37   def run(%SourceFile{} = source_file, params) do
     38     issue_meta = IssueMeta.for(source_file, params)
     39     # {<Logger import seen?>, <list of issues>}
     40     state = {false, []}
     41 
     42     {_, issues} = Credo.Code.prewalk(source_file, &traverse(&1, &2, issue_meta), state)
     43 
     44     issues
     45   end
     46 
     47   defp traverse(
     48          {{:., _, [{:__aliases__, _, [:Logger]}, fun_name]}, meta, arguments} = ast,
     49          state,
     50          issue_meta
     51        )
     52        when fun_name in @logger_functions do
     53     issue = find_issue(fun_name, arguments, meta, issue_meta)
     54 
     55     {ast, add_issue_to_state(state, issue)}
     56   end
     57 
     58   defp traverse(
     59          {fun_name, meta, arguments} = ast,
     60          {true, _issues} = state,
     61          issue_meta
     62        )
     63        when fun_name in @logger_functions do
     64     issue = find_issue(fun_name, arguments, meta, issue_meta)
     65 
     66     {ast, add_issue_to_state(state, issue)}
     67   end
     68 
     69   defp traverse(
     70          {:import, _meta, arguments} = ast,
     71          {_module_contains_import?, issues} = state,
     72          _issue_meta
     73        ) do
     74     if logger_import?(arguments) do
     75       {ast, {true, issues}}
     76     else
     77       {ast, state}
     78     end
     79   end
     80 
     81   defp traverse(ast, state, _issue_meta) do
     82     {ast, state}
     83   end
     84 
     85   defp add_issue_to_state(state, nil), do: state
     86 
     87   defp add_issue_to_state({module_contains_import?, issues}, issue) do
     88     {module_contains_import?, [issue | issues]}
     89   end
     90 
     91   defp find_issue(fun_name, arguments, meta, issue_meta) do
     92     params = IssueMeta.params(issue_meta)
     93     ignored_functions = Params.get(params, :ignore, __MODULE__)
     94 
     95     unless Enum.member?(ignored_functions, fun_name) do
     96       issue_for_call(arguments, meta, issue_meta)
     97     end
     98   end
     99 
    100   defp issue_for_call([{:<<>>, _, [_ | _]} | _] = _args, meta, issue_meta) do
    101     issue_for(issue_meta, meta[:line])
    102   end
    103 
    104   defp issue_for_call(_args, _meta, _issue_meta) do
    105     nil
    106   end
    107 
    108   defp logger_import?([{:__aliases__, _meta, [:Logger]}]), do: true
    109   defp logger_import?(_), do: false
    110 
    111   defp issue_for(issue_meta, line_no) do
    112     format_issue(
    113       issue_meta,
    114       message: "Prefer lazy Logger calls.",
    115       line_no: line_no
    116     )
    117   end
    118 end