Current section

Files

Jump to
timber lib timber events http_client_response_event.ex
Raw

lib/timber/events/http_client_response_event.ex

defmodule Timber.Events.HTTPClientResponseEvent do
@moduledoc """
The `HTTPClientResponseEvent` tracks responses for *outgoing* HTTP *requests*. This gives you
structured insight into communication with external services.
See `Timber.Events.HTTPClientRequestEvent` for examples on track the entire HTTP request
lifecycle.
"""
alias Timber.Utils.HTTP, as: UtilsHTTP
@enforce_keys [:status, :time_ms]
defstruct [:headers, :service_name, :status, :time_ms]
@type t :: %__MODULE__{
headers: headers,
service_name: String.t | nil,
status: pos_integer,
time_ms: float
}
@type headers :: %{
cache_control: String.t,
content_disposition: String.t,
content_length: non_neg_integer,
content_type: String.t,
location: String.t,
request_id: String.t
}
@recognized_headers ~w(
cache_control
content_disposition
content_length
content_type
location
x-request-id
)
@doc """
Builds a new struct taking care to normalize data into a valid state. This should
be used, where possible, instead of creating the struct directly.
"""
@spec new(Keyword.t) :: t
def new(opts) do
opts =
opts
|> Keyword.update(:headers, nil, fn headers ->
UtilsHTTP.normalize_headers(headers, @recognized_headers)
end)
|> Keyword.delete(:timer)
|> Enum.filter(fn {_k,v} -> v != nil end)
struct!(__MODULE__, opts)
end
@doc """
Convenience methods for creating an event and getting the message at the same time.
"""
@spec new_with_message(Keyword.t) :: {t, IO.chardata}
def new_with_message(opts) do
event = new(opts)
{event, message(event)}
end
@doc """
Message to be used when logging.
"""
@spec message(t) :: IO.chardata
def message(%__MODULE__{headers: headers, service_name: service_name, status: status,
time_ms: time_ms})
do
message = ["Outgoing HTTP response "]
message = if service_name,
do: [message, "from ", service_name, " "],
else: message
message = [message, Integer.to_string(status), " in ", UtilsHTTP.format_time_ms(time_ms)]
request_id = Map.get(headers || %{}, :request_id)
if request_id,
do: [message, ", ID ", request_id],
else: message
end
end