zf

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

logger.ex (4323B)


      1 defmodule Absinthe.Logger do
      2   @default_log true
      3   @default_filter_variables ~w(token password)
      4   @default_pipeline false
      5 
      6   @moduledoc """
      7   Handles logging of Absinthe-specific events.
      8 
      9   ## Variable filtering
     10 
     11   Absinthe can filter out sensitive information like tokens and passwords
     12   during logging. They are replaced by `"[FILTERED]"`.
     13 
     14   Use the `:filter_variables` configuration setting for this module.
     15   For example:
     16 
     17       config :absinthe, Absinthe.Logger,
     18         filter_variables: ["token", "password", "secret"]
     19 
     20   With the configuration above, Absinthe will filter any variable whose name
     21   includes the terms `token`, `password`, or `secret`. The match is case
     22   sensitive.
     23 
     24   Note that filtering only applies to GraphQL variables - the query itself is
     25   logged before any parsing happens.
     26 
     27   The default is `#{inspect(@default_filter_variables)}`.
     28 
     29   ## Pipeline display
     30 
     31   Absinthe can optionally display the list of pipeline phases for each processed
     32   document when logging. To enable this feature, set the `:pipeline`
     33   configuration option for this module:
     34 
     35       config :absinthe, Absinthe.Logger,
     36         pipeline: true
     37 
     38   The default is `#{inspect(@default_pipeline)}`.
     39 
     40   ## Disabling
     41 
     42   To disable Absinthe logging, set the `:log` configuration option to `false`:
     43 
     44       config :absinthe,
     45         log: false
     46 
     47   The default is `#{inspect(@default_log)}`.
     48 
     49   """
     50   require Logger
     51 
     52   @doc """
     53   Log a document being processed.
     54   """
     55   @spec log_run(
     56           level :: Logger.level(),
     57           {doc :: Absinthe.Pipeline.data_t(), schema :: Absinthe.Schema.t(),
     58            pipeline :: Absinthe.Pipeline.t(), opts :: Keyword.t()}
     59         ) :: :ok
     60   def log_run(level, {doc, schema, pipeline, opts}) do
     61     if Application.get_env(:absinthe, :log, @default_log) do
     62       Logger.log(level, fn ->
     63         [
     64           "ABSINTHE",
     65           " schema=",
     66           inspect(schema),
     67           " variables=",
     68           variables_body(opts),
     69           pipeline_section(pipeline),
     70           "---",
     71           ?\n,
     72           document(doc),
     73           ?\n,
     74           "---"
     75         ]
     76       end)
     77     end
     78 
     79     :ok
     80   end
     81 
     82   @doc false
     83   @spec document(Absinthe.Pipeline.data_t()) :: binary
     84   def document(value) when value in ["", nil] do
     85     "[EMPTY]"
     86   end
     87 
     88   def document(%Absinthe.Blueprint{name: nil}) do
     89     "[COMPILED]"
     90   end
     91 
     92   def document(%Absinthe.Blueprint{name: name}) do
     93     "[COMPILED#<#{name}>]"
     94   end
     95 
     96   def document(%Absinthe.Language.Source{body: body}) do
     97     document(body)
     98   end
     99 
    100   def document(document) when is_binary(document) do
    101     String.trim(document)
    102   end
    103 
    104   def document(other) do
    105     inspect(other)
    106   end
    107 
    108   @doc false
    109   @spec filter_variables(map) :: map
    110   @spec filter_variables(map, [String.t()]) :: map
    111   def filter_variables(data, filter_variables \\ variables_to_filter())
    112 
    113   def filter_variables(%{__struct__: mod} = struct, _filter_variables) when is_atom(mod) do
    114     struct
    115   end
    116 
    117   def filter_variables(%{} = map, filter_variables) do
    118     Enum.into(map, %{}, fn {k, v} ->
    119       if is_binary(k) and String.contains?(k, filter_variables) do
    120         {k, "[FILTERED]"}
    121       else
    122         {k, filter_variables(v, filter_variables)}
    123       end
    124     end)
    125   end
    126 
    127   def filter_variables([_ | _] = list, filter_variables) do
    128     Enum.map(list, &filter_variables(&1, filter_variables))
    129   end
    130 
    131   def filter_variables(other, _filter_variables), do: other
    132 
    133   @spec variables_to_filter() :: [String.t()]
    134   defp variables_to_filter do
    135     Application.get_env(:absinthe, __MODULE__, [])
    136     |> Keyword.get(:filter_variables, @default_filter_variables)
    137   end
    138 
    139   @spec variables_body(Keyword.t()) :: String.t()
    140   defp variables_body(opts) do
    141     Keyword.get(opts, :variables, %{})
    142     |> filter_variables()
    143     |> inspect()
    144   end
    145 
    146   @spec pipeline_section(Absinthe.Pipeline.t()) :: iolist
    147   defp pipeline_section(pipeline) do
    148     Application.get_env(:absinthe, __MODULE__, [])
    149     |> Keyword.get(:pipeline, @default_pipeline)
    150     |> case do
    151       true ->
    152         do_pipeline_section(pipeline)
    153 
    154       false ->
    155         ?\n
    156     end
    157   end
    158 
    159   @spec do_pipeline_section(Absinthe.Pipeline.t()) :: iolist
    160   defp do_pipeline_section(pipeline) do
    161     [
    162       " pipeline=",
    163       pipeline
    164       |> Enum.map(fn
    165         {mod, _} -> mod
    166         mod -> mod
    167       end)
    168       |> inspect,
    169       ?\n
    170     ]
    171   end
    172 end