| defmodule MedicodeWeb.MetricsStorage 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 |
|
|