diff --git a/lib/towerops_web/live/equipment_live/show.html.heex b/lib/towerops_web/live/equipment_live/show.html.heex index 501529aa..ddf9bcbf 100644 --- a/lib/towerops_web/live/equipment_live/show.html.heex +++ b/lib/towerops_web/live/equipment_live/show.html.heex @@ -73,14 +73,24 @@ <%= if @traffic_chart_data do %>
-
-

- Overall Traffic (24 Hours) -

-

- Combined traffic across all interfaces -

-
+ <.link + navigate={ + ~p"/orgs/#{@current_organization.slug}/equipment/#{@equipment.id}/graph/traffic" + } + class="block px-4 py-3 border-b border-zinc-200 dark:border-zinc-700 hover:bg-zinc-50 dark:hover:bg-zinc-750 transition-colors" + > +
+
+

+ Overall Traffic (24 Hours) +

+

+ Combined traffic across all interfaces +

+
+ <.icon name="hero-arrow-right" class="h-4 w-4 text-zinc-400" /> +
+
+ nil + + device -> + if Enum.empty?(device.interfaces) do + nil + else + since = get_datetime_from_range(range) + limit = get_limit_for_range(range) + + # Get all stats for all interfaces + all_stats = + device.interfaces + |> Enum.flat_map(fn interface -> + stats = + interface.id + |> Snmp.get_interface_stats(since: since, limit: limit) + |> Enum.reverse() + + Enum.map(stats, fn stat -> + {stat.checked_at, stat.if_in_octets, stat.if_out_octets} + end) + end) + |> Enum.group_by(&elem(&1, 0)) + |> Enum.map(fn {timestamp, stats} -> + total_in = + Enum.reduce(stats, 0, fn {_, in_octets, _}, acc -> acc + (in_octets || 0) end) + + total_out = + Enum.reduce(stats, 0, fn {_, _, out_octets}, acc -> acc + (out_octets || 0) end) + + {timestamp, total_in, total_out} + end) + |> Enum.sort_by(&elem(&1, 0), DateTime) + + if Enum.empty?(all_stats) do + nil + else + # Calculate bits per second from counter differences + in_data = + all_stats + |> Enum.chunk_every(2, 1, :discard) + |> Enum.map(fn [{t1, in1, _out1}, {t2, in2, _out2}] -> + time_diff = t2 |> DateTime.diff(t1, :second) |> max(1) + bps = ((in2 - in1) * 8 / time_diff) |> max(0) |> Float.round(2) + + %{ + x: DateTime.to_unix(t2, :millisecond), + y: bps + } + end) + + out_data = + all_stats + |> Enum.chunk_every(2, 1, :discard) + |> Enum.map(fn [{t1, _in1, out1}, {t2, _in2, out2}] -> + time_diff = t2 |> DateTime.diff(t1, :second) |> max(1) + bps = ((out2 - out1) * 8 / time_diff) |> max(0) |> Float.round(2) + + %{ + x: DateTime.to_unix(t2, :millisecond), + y: bps + } + end) + + datasets = [ + %{label: "Inbound", data: in_data}, + %{label: "Outbound", data: out_data} + ] + + Jason.encode!(%{datasets: datasets}) + end + end + end + end end