Current section

Files

Jump to
funx lib summarizable.ex
Raw

lib/summarizable.ex

defprotocol Funx.Summarizable do
@doc "Summarizes a value in a telemetry-safe, compact format."
@fallback_to_any true
@spec summarize(t) :: term()
def summarize(value)
end
defimpl Funx.Summarizable, for: Any do
def summarize(%mod{} = value) when is_struct(value) do
value
|> Map.from_struct()
|> Map.put(:__module__, mod)
|> Funx.Summarizable.summarize()
end
# coveralls-ignore-next-line
def summarize(_), do: :unknown
end
defimpl Funx.Summarizable, for: Atom do
def summarize(nil), do: nil
def summarize(atom), do: {:atom, atom}
end
defimpl Funx.Summarizable, for: Integer do
def summarize(value), do: {:integer, value}
end
defimpl Funx.Summarizable, for: Float do
def summarize(value), do: {:float, value}
end
defimpl Funx.Summarizable, for: BitString do
def summarize(value) when is_binary(value) do
if String.valid?(value) do
{:string, Funx.Utils.summarize_string(value, 50)}
else
{:binary, byte_size(value)}
end
end
def summarize(value) do
{:bitstring, "<<#{:erlang.bit_size(value)} bits>>"}
end
end
defimpl Funx.Summarizable, for: List do
def summarize([]), do: {:list, :empty}
def summarize(list) do
{:list, Enum.take(list, 3) |> Enum.map(&Funx.Summarizable.summarize/1)}
end
end
defimpl Funx.Summarizable, for: Map do
def summarize(map) when map_size(map) == 0, do: {:map, :empty}
def summarize(map) do
map
|> Enum.sort_by(fn {k, _} -> k end)
|> Enum.take(3)
|> Enum.map(fn {k, v} -> {k, Funx.Summarizable.summarize(v)} end)
|> then(&{:map, &1})
end
end
defimpl Funx.Summarizable, for: Tuple do
def summarize(tup) when tuple_size(tup) == 0, do: {:tuple, :empty}
def summarize(tup) do
tup
|> Tuple.to_list()
|> Enum.take(3)
|> Enum.map(&Funx.Summarizable.summarize/1)
|> then(&{:tuple, &1})
end
end
defimpl Funx.Summarizable, for: Function do
def summarize(_), do: :function
end
defimpl Funx.Summarizable, for: PID do
def summarize(_), do: :pid
end
defimpl Funx.Summarizable, for: Port do
def summarize(_), do: :port
end
defimpl Funx.Summarizable, for: Reference do
def summarize(_), do: :reference
end
defimpl Funx.Summarizable, for: RuntimeError do
def summarize(%RuntimeError{message: msg}), do: {:exception, {:runtime, msg}}
end
defimpl Funx.Summarizable, for: FunctionClauseError do
def summarize(error),
do: {:exception, {FunctionClauseError, Exception.message(error)}}
end