defmodule DalaDev.Server.ObserverLive.Ports do @moduledoc "LiveView for ports information display." use Phoenix.LiveView, layout: {DalaDev.Server.Layouts, :app} alias DalaDev.Observer @refresh_interval 5_000 def mount(_params, _session, socket) do if connected?(socket), do: :timer.send_interval(@refresh_interval, self(), :refresh) socket = socket |> assign(:node, Node.self()) |> assign(:available_nodes, [Node.self() | Node.list()]) |> assign(:ports, []) |> assign(:error, nil) |> assign(:loading, false) {:ok, fetch_ports(socket)} end def handle_params(%{"node" => node_str}, _uri, socket) do try do node = String.to_existing_atom(":#{node_str}") {:noreply, assign(socket, :node, node) |> fetch_ports()} rescue _ -> {:noreply, assign(socket, :error, "Invalid node name: #{node_str}")} end end def handle_params(_params, _uri, socket), do: {:noreply, socket} def handle_info(:refresh, socket), do: {:noreply, fetch_ports(socket)} def handle_event("refresh", _params, socket), do: {:noreply, fetch_ports(socket)} def handle_event("select_node", %{"node" => node_str}, socket) do try do node = String.to_existing_atom(node_str) {:noreply, assign(socket, :node, node) |> fetch_ports()} rescue _ -> {:noreply, assign(socket, :error, "Invalid node: #{node_str}")} end end def render(assigns) do ~H"""
← Back

Ports: <%= @node %>

<%= if @error do %>

<%= @error %>

<% end %>
<%= for port <- @ports do %> <% end %>
Port ID Name Input Output Connected To OS PID
<%= port.id %> <%= port.name %> <%= format_bytes(port.input) %> <%= format_bytes(port.output) %> <%= port.connected %> <%= port.os_pid || "-" %>
""" end defp fetch_ports(socket) do node = socket.assigns[:node] socket = socket |> assign(:loading, true) |> assign(:available_nodes, [Node.self() | Node.list()]) case Observer.observe(node) do {:ok, data} -> ports = data[:ports] || [] assign(socket, :ports, ports) |> assign(:error, nil) |> assign(:loading, false) {:error, reason} -> assign(socket, :error, "Failed: #{reason}") |> assign(:loading, false) end end defp format_bytes(nil), do: "0 B" defp format_bytes(bytes) when bytes < 1024, do: "#{bytes} B" defp format_bytes(bytes) when bytes < 1024 * 1024, do: "#{Float.round(bytes / 1024, 1)} KB" defp format_bytes(bytes) when bytes < 1024 * 1024 * 1024, do: "#{Float.round(bytes / (1024 * 1024), 1)} MB" defp format_bytes(bytes), do: "#{Float.round(bytes / (1024 * 1024 * 1024), 1)} GB" end