defmodule DalaDev.Server.ObserverLive do @moduledoc """ Main Observer dashboard with navigation to specialized views. Provides an overview of all nodes and quick access to detailed views for system info, processes, ETS tables, applications, etc. """ 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) end socket = socket |> assign(:node, Node.self()) |> assign(:available_nodes, [Node.self() | Node.list()]) |> assign(:summary, nil) |> assign(:error, nil) |> assign(:loading, false) {:ok, fetch_summary(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_summary()} rescue _ -> {:noreply, assign(socket, :error, "Invalid node name: #{node_str}")} end end def handle_params(_params, _uri, socket) do {:noreply, socket} end def handle_info(:refresh, socket) do {:noreply, fetch_summary(socket)} end def handle_event("refresh", _params, socket) do {:noreply, fetch_summary(socket)} end 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_summary()} rescue _ -> {:noreply, assign(socket, :error, "Invalid node: #{node_str}")} end end def render(assigns) do ~H"""
<%= @error %>
Memory, uptime, version, and system statistics
Process list with sorting, filtering, and details
ETS tables browser with memory and ownership info
Running applications with versions
Loaded modules and memory usage
Port information and I/O statistics
Scheduler usage and I/O statistics
Process tracing and message flow analysis