Keep telemetry metrics history
This commit is contained in:
@@ -67,6 +67,7 @@ defmodule MusicLibraryWeb.Router do
|
||||
|
||||
live_dashboard "/dashboard",
|
||||
metrics: MusicLibraryWeb.Telemetry,
|
||||
metrics_history: {MusicLibraryWeb.Telemetry.Storage, :metrics_history, []},
|
||||
ecto_repos: [MusicLibrary.Repo]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,6 +9,7 @@ defmodule MusicLibraryWeb.Telemetry do
|
||||
@impl true
|
||||
def init(_arg) do
|
||||
children = [
|
||||
{MusicLibraryWeb.Telemetry.Storage, metrics()},
|
||||
# Telemetry poller will execute the given period measurements
|
||||
# every 10_000ms. Learn more here: https://hexdocs.pm/telemetry_metrics
|
||||
{:telemetry_poller, measurements: periodic_measurements(), period: 10_000}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
defmodule MusicLibraryWeb.Telemetry.Storage 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
|
||||
Reference in New Issue
Block a user