67 lines
1.5 KiB
Elixir
67 lines
1.5 KiB
Elixir
|
defmodule Wiki.MetricStorage do
|
||
|
use GenServer
|
||
|
|
||
|
@history_buffer_size 50
|
||
|
|
||
|
def metrics_history(metric) do
|
||
|
GenServer.call(__MODULE__, {:data, metric})
|
||
|
end
|
||
|
|
||
|
def start_link(args) do
|
||
|
GenServer.start_link(__MODULE__, args, name: __MODULE__)
|
||
|
end
|
||
|
|
||
|
@impl true
|
||
|
def init(metrics) do
|
||
|
Process.flag(:trap_exit, true)
|
||
|
|
||
|
metric_histories_map =
|
||
|
metrics
|
||
|
|> Enum.map(fn metric ->
|
||
|
attach_handler(metric)
|
||
|
{metric, CircularBuffer.new(@history_buffer_size)}
|
||
|
end)
|
||
|
|> Map.new()
|
||
|
|
||
|
{:ok, metric_histories_map}
|
||
|
end
|
||
|
|
||
|
@impl true
|
||
|
def terminate(_, metrics) do
|
||
|
for metric <- metrics do
|
||
|
:telemetry.detach({__MODULE__, metric, self()})
|
||
|
end
|
||
|
|
||
|
:ok
|
||
|
end
|
||
|
|
||
|
defp attach_handler(%{event_name: name_list} = metric) do
|
||
|
:telemetry.attach(
|
||
|
{__MODULE__, metric, self()},
|
||
|
name_list,
|
||
|
&__MODULE__.handle_event/4,
|
||
|
metric
|
||
|
)
|
||
|
end
|
||
|
|
||
|
def handle_event(_event_name, data, metadata, metric) do
|
||
|
if data = Phoenix.LiveDashboard.extract_datapoint_for_metric(metric, data, metadata) do
|
||
|
GenServer.cast(__MODULE__, {:telemetry_metric, data, metric})
|
||
|
end
|
||
|
end
|
||
|
|
||
|
@impl true
|
||
|
def handle_cast({:telemetry_metric, data, metric}, state) do
|
||
|
{:noreply, update_in(state[metric], &CircularBuffer.insert(&1, data))}
|
||
|
end
|
||
|
|
||
|
@impl true
|
||
|
def handle_call({:data, metric}, _from, state) do
|
||
|
if history = state[metric] do
|
||
|
{:reply, CircularBuffer.to_list(history), state}
|
||
|
else
|
||
|
{:reply, [], state}
|
||
|
end
|
||
|
end
|
||
|
end
|