defmodule Nebulex.Telemetry.StatsHandler do @moduledoc """ Telemetry handler for aggregating cache stats; it relies on the default stats implementation based on Erlang counters. See `Nebulex.Adapter.Stats`. This handler is used by the built-in local adapter when the option `:stats` is set to `true`. """ alias Nebulex.Adapter.Stats ## Handler @doc false def handle_event(_event, _measurements, %{adapter_meta: %{stats_counter: ref}} = metadata, ref) do update_stats(metadata) end # coveralls-ignore-start def handle_event(_event, _measurements, _metadata, _ref) do :ok end # coveralls-ignore-stop defp update_stats(%{ function_name: action, result: :"$expired", adapter_meta: %{stats_counter: ref} }) when action in [:get, :take, :ttl] do :ok = Stats.incr(ref, :misses) :ok = Stats.incr(ref, :evictions) :ok = Stats.incr(ref, :expirations) end defp update_stats(%{function_name: action, result: nil, adapter_meta: %{stats_counter: ref}}) when action in [:get, :take, :ttl] do :ok = Stats.incr(ref, :misses) end defp update_stats(%{function_name: action, result: _, adapter_meta: %{stats_counter: ref}}) when action in [:get, :ttl] do :ok = Stats.incr(ref, :hits) end defp update_stats(%{function_name: :take, result: _, adapter_meta: %{stats_counter: ref}}) do :ok = Stats.incr(ref, :hits) :ok = Stats.incr(ref, :evictions) end defp update_stats(%{ function_name: :put, args: [_, _, _, :replace, _], result: true, adapter_meta: %{stats_counter: ref} }) do :ok = Stats.incr(ref, :updates) end defp update_stats(%{function_name: :put, result: true, adapter_meta: %{stats_counter: ref}}) do :ok = Stats.incr(ref, :writes) end defp update_stats(%{ function_name: :put_all, result: true, args: [entries | _], adapter_meta: %{stats_counter: ref} }) do :ok = Stats.incr(ref, :writes, Enum.count(entries)) end defp update_stats(%{function_name: :delete, result: _, adapter_meta: %{stats_counter: ref}}) do :ok = Stats.incr(ref, :evictions) end defp update_stats(%{ function_name: :execute, args: [:delete_all | _], result: result, adapter_meta: %{stats_counter: ref} }) do :ok = Stats.incr(ref, :evictions, result) end defp update_stats(%{function_name: action, result: true, adapter_meta: %{stats_counter: ref}}) when action in [:expire, :touch] do :ok = Stats.incr(ref, :updates) end defp update_stats(%{ function_name: :update_counter, args: [_, amount, _, default, _], result: result, adapter_meta: %{stats_counter: ref} }) do offset = if amount >= 0, do: -1, else: 1 if result + amount * offset === default do :ok = Stats.incr(ref, :writes) else :ok = Stats.incr(ref, :updates) end end defp update_stats(_), do: :ok end