defmodule Vibe.Web.RuntimeLive do @moduledoc """ LiveView runtime dashboard for Vibe's BEAM process. """ use Vibe.Web, :live_view alias Vibe.OTP @impl true def mount(_params, _session, socket) do if connected?(socket), do: :timer.send_interval(2_000, :refresh) {:ok, assign_runtime(socket)} end @impl true def handle_info(:refresh, socket), do: {:noreply, assign_runtime(socket)} @impl true def render(assigns) do ~H""" <.app_shell current={:runtime} title="Runtime" subtitle="Local Vibe server health, resource use, and background activity."> <.panel title="Node"> OTP{@runtime.otp_release} Elixir{@runtime.elixir} Schedulers{@runtime.schedulers} Active sessions{@active_count} <.stat_card label="Processes" value={@runtime.process_count} /> <.stat_card label="ETS tables" value={length(@ets)} accent="text-vibe-accent" /> <.stat_card label="Memory MB" value={memory_mb(@runtime.memory[:total])} accent="text-cyan-300" /> <.panel title="Top processes by memory"> #PIDNameMemoryQueue {process.index} {process.pid} {inspect(process.name || process.initial_call)} {process.memory} {process.message_queue_len} <.panel title="Largest ETS tables"> NameSizeMemory {inspect(table.name || table.id)} {table.size} {table.memory} """ end defp assign_runtime(socket) do socket |> assign(:runtime, OTP.runtime_info()) |> assign(:top, OTP.top(:memory, limit: 12)) |> assign(:ets, OTP.ets_tables(limit: 12)) |> assign(:active_count, Vibe.Session.active_count()) end defp memory_mb(nil), do: 0 defp memory_mb(bytes), do: Float.round(bytes / 1_048_576, 1) end