towerops/lib/towerops_web/live/site_live/show.ex
Graham McIntire 35ca827bd0
Add latency graph to site detail page
Shows ping latency for all devices in the site over the last 24 hours.
Each device is displayed as a separate line on the graph with its name
as the label.

Graph only appears if there is latency data available for at least
one device in the site.
2026-01-17 16:58:59 -06:00

64 lines
1.6 KiB
Elixir

defmodule ToweropsWeb.SiteLive.Show do
@moduledoc false
use ToweropsWeb, :live_view
alias Towerops.Devices
alias Towerops.Monitoring
alias Towerops.Sites
@impl true
def mount(_params, _session, socket) do
{:ok, socket}
end
@impl true
def handle_params(%{"id" => id}, _, socket) do
organization = socket.assigns.current_organization
site = Sites.get_organization_site!(organization.id, id)
device = Devices.list_site_devices(site.id)
latency_chart_data = load_site_latency_chart_data(device)
{:noreply,
socket
|> assign(:page_title, site.name)
|> assign(:site, site)
|> assign(:device, device)
|> assign(:latency_chart_data, latency_chart_data)}
end
defp load_site_latency_chart_data(devices) do
if Enum.empty?(devices) do
nil
else
twenty_four_hours_ago = DateTime.add(DateTime.utc_now(), -24, :hour)
datasets =
devices
|> Enum.map(fn device ->
checks =
device.id
|> Monitoring.get_latency_data(since: twenty_four_hours_ago, limit: 1000)
|> Enum.reverse()
%{
label: device.name,
data: Enum.map(checks, &latency_check_to_data_point/1)
}
end)
|> Enum.reject(fn dataset -> Enum.empty?(dataset.data) end)
if Enum.empty?(datasets) do
nil
else
Jason.encode!(%{datasets: datasets})
end
end
end
defp latency_check_to_data_point(check) do
%{
x: DateTime.to_unix(check.checked_at, :millisecond),
y: check.response_time_ms
}
end
end