lib/pre_log_plug.ex

defmodule TimeLog.PreLogPlug do
  require Logger
  alias TimeLog.TimePlug

  @moduledoc ~S"""
  This plug logs the incoming requests.
  It logs the IP address and has the ability to anonymize the IP address if set in config.
  """

  @doc false
  def init(_opts) do
    {}
  end

  @doc "Call to PreLogPlug that initiates the request logging."
  @spec call(Plug.Conn, Map) :: Plug.Conn
  def call(conn, _opts) do
    if is_list(TimePlug.from_config(:ignore_urls)) and
         conn.request_path in TimePlug.from_config(:ignore_urls) do
      conn
    else
      initiate_logging(conn)
    end
  end

  @doc ~S"""
  Initiates Response logging and logs the incoming request.
  Ensures that responses are only logged if the corresponding request was logged as well.
  """
  @spec initiate_logging(Plug.Conn) :: Plug.Conn
  def initiate_logging(conn) do
    c_id = TimePlug.get_correlation_id(conn)

    http_map = %{
      method: conn.method,
      url: conn.request_path,
      query: TimePlug.sanitize_query_string(conn),
      ip_address: TimePlug.get_ip(conn),
      header: inspect(conn.req_headers),
      params: TimePlug.sanitize(conn.params)
    }

    http_map =
      if TimePlug.from_config(:remove_headers?) do
        Map.drop(http_map, [:header])
      else
        http_map
      end

    Logger.info(Jason.encode!(%{correlation_id: c_id, type: "Request", http: http_map}), request_log: 1)
    Plug.Conn.register_before_send(conn, &TimePlug.log_response(&1))
  end
end