defmodule SuperintelligenceWeb.DashboardLive do
use SuperintelligenceWeb, :live_view
alias Superintelligence.{TelemetryReporter, WorkerPool, ResourceManager, HealthMonitor}
@refresh_interval 1000
def mount(_params, _session, socket) do
if connected?(socket) do
:timer.send_interval(@refresh_interval, self(), :tick)
Phoenix.PubSub.subscribe(Superintelligence.PubSub, "telemetry:updates")
Phoenix.PubSub.subscribe(Superintelligence.PubSub, "worker:updates")
Phoenix.PubSub.subscribe(Superintelligence.PubSub, "health:updates")
end
socket =
socket
|> assign(:page_title, "Superintelligence Dashboard")
|> assign(:metrics, get_metrics())
|> assign(:workers, get_workers())
|> assign(:health_checks, get_health_checks())
|> assign(:resource_usage, get_resource_usage())
|> assign(:system_info, get_system_info())
|> assign(:performance_data, get_performance_data())
|> assign(:ai_models, get_ai_models())
|> assign(:active_tasks, get_active_tasks())
{:ok, socket}
end
def handle_info(:tick, socket) do
socket =
socket
|> assign(:metrics, get_metrics())
|> assign(:workers, get_workers())
|> assign(:health_checks, get_health_checks())
|> assign(:resource_usage, get_resource_usage())
|> assign(:performance_data, get_performance_data())
|> assign(:active_tasks, get_active_tasks())
{:noreply, socket}
end
def handle_info({:telemetry_update, data}, socket) do
{:noreply, update(socket, :metrics, fn metrics ->
Map.merge(metrics, data)
end)}
end
def handle_info({:worker_update, data}, socket) do
{:noreply, assign(socket, :workers, data)}
end
def handle_info({:health_update, data}, socket) do
{:noreply, assign(socket, :health_checks, data)}
end
def handle_event("deploy_model", %{"model_id" => model_id}, socket) do
# Handle model deployment
send(self(), {:deploy_model, model_id})
{:noreply, put_flash(socket, :info, "Deploying model #{model_id}...")}
end
def handle_event("scale_workers", %{"count" => count}, socket) do
# Handle worker scaling
WorkerPool.scale_workers(String.to_integer(count))
{:noreply, put_flash(socket, :info, "Scaling workers to #{count}")}
end
def handle_event("execute_task", %{"task_type" => task_type}, socket) do
# Handle task execution
task_id = UUID.uuid4()
WorkerPool.submit_task(%{id: task_id, type: task_type, priority: :high})
{:noreply, put_flash(socket, :info, "Task #{task_id} submitted")}
end
def render(assigns) do
~H"""
Superintelligence Control Center
Real-time monitoring and control
<.metric_card title="Active Workers" value={@workers.active_count} icon="hero-cpu-chip" color="blue" />
<.metric_card title="Tasks/Second" value={@metrics[:tasks_per_second] || 0} icon="hero-bolt" color="green" />
<.metric_card title="System Health" value={@health_checks.overall_health} icon="hero-heart" color="red" />
<.metric_card title="Memory Usage" value={format_bytes(@resource_usage.memory)} icon="hero-chart-bar" color="purple" />
<.panel title="Worker Pool Status">
Total Workers
{@workers.total_count}
<.worker_status_chart workers={@workers} />
<.performance_graph data={@performance_data} />
Worker Details
<%= for worker <- @workers.workers do %>
<.worker_row worker={worker} />
<% end %>
<.panel title="AI Models">
<%= for model <- @ai_models do %>
<.model_card model={model} />
<% end %>
<.panel title="Health Checks">
<%= for {name, check} <- @health_checks.checks do %>
<.health_check_row name={name} check={check} />
<% end %>
<.panel title="Active Tasks">
<%= for task <- @active_tasks do %>
<.task_row task={task} />
<% end %>
<.panel title="Resource Usage">
<.resource_meter title="CPU" value={@resource_usage.cpu_percent} max={100} unit="%" />
<.resource_meter title="Memory" value={@resource_usage.memory_percent} max={100} unit="%" />
<.resource_meter title="GPU" value={@resource_usage.gpu_percent || 0} max={100} unit="%" />
<.panel title="System Information">
Uptime
{format_uptime(@system_info.uptime)}
Nodes
{@system_info.node_count}
Version
{@system_info.version}
Environment
{@system_info.env}
"""
end
# Component Functions
defp metric_card(assigns) do
~H"""
<.icon name={@icon} class="w-8 h-8" />
"""
end
defp panel(assigns) do
~H"""
{@title}
<%= render_slot(@inner_block) %>
"""
end
defp worker_row(assigns) do
~H"""
Tasks: {@worker.tasks_completed}
CPU: {@worker.cpu_usage}%
{@worker.status}
"""
end
defp worker_status_chart(assigns) do
~H"""
Status Distribution
<.status_bar label="Active" count={@workers.active_count} total={@workers.total_count} color="green" />
<.status_bar label="Idle" count={@workers.idle_count} total={@workers.total_count} color="yellow" />
<.status_bar label="Error" count={@workers.error_count} total={@workers.total_count} color="red" />
"""
end
defp status_bar(assigns) do
percentage = if assigns.total > 0, do: assigns.count / assigns.total * 100, else: 0
assigns = assign(assigns, :percentage, percentage)
~H"""
"""
end
defp performance_graph(assigns) do
~H"""
Performance
<%= for point <- @data do %>
<% end %>
"""
end
defp model_card(assigns) do
~H"""
{@model.name}
{@model.status}
Type: {@model.type}
Accuracy: {@model.accuracy}%
Latency: {@model.latency}ms
"""
end
defp health_check_row(assigns) do
~H"""
{@name}
Last: {@check.last_check_ago}s ago
"""
end
defp task_row(assigns) do
~H"""
{@task.type}
ID: {@task.id}
Worker {@task.worker_id}
<.progress_ring progress={@task.progress} />
"""
end
defp progress_ring(assigns) do
circumference = 2 * :math.pi() * 16
stroke_dashoffset = circumference - (assigns.progress / 100 * circumference)
assigns = assign(assigns, :circumference, circumference)
assigns = assign(assigns, :stroke_dashoffset, stroke_dashoffset)
~H"""
{@progress}%
"""
end
defp resource_meter(assigns) do
~H"""
"""
end
# Helper Functions
defp get_metrics do
case TelemetryReporter.get_metrics() do
{:ok, metrics} -> metrics
_ -> %{}
end
end
defp get_workers do
case WorkerPool.get_status() do
status when is_map(status) ->
workers = status[:workers] || []
%{
workers: workers,
total_count: length(workers),
active_count: Enum.count(workers, & &1.status == :busy),
idle_count: Enum.count(workers, & &1.status == :idle),
error_count: Enum.count(workers, & &1.status == :error)
}
_ ->
%{workers: [], total_count: 0, active_count: 0, idle_count: 0, error_count: 0}
end
end
defp get_health_checks do
try do
status = HealthMonitor.get_health_status()
%{
checks: status.checks || %{},
overall_health: status.overall || "Unknown"
}
rescue
_ ->
%{checks: %{}, overall_health: "Unknown"}
end
end
defp get_resource_usage do
case ResourceManager.get_usage() do
{:ok, usage} ->
%{
memory: usage[:memory] || 0,
memory_percent: (usage[:memory] || 0) / :erlang.memory(:total) * 100,
cpu_percent: usage[:cpu] || 0,
gpu_percent: usage[:gpu]
}
_ ->
%{memory: 0, memory_percent: 0, cpu_percent: 0, gpu_percent: 0}
end
end
defp get_system_info do
%{
uptime: :erlang.system_info(:uptime) |> elem(0),
node_count: length(Node.list()) + 1,
version: Application.spec(:superintelligence, :vsn) |> to_string(),
env: Mix.env() |> to_string()
}
end
defp get_performance_data do
# Generate sample performance data
Enum.map(1..20, fn _ -> :rand.uniform(100) end)
end
defp get_ai_models do
[
%{id: 1, name: "GPT-4 Turbo", type: "LLM", status: :active, accuracy: 98.5, latency: 120},
%{id: 2, name: "BERT-Large", type: "NLP", status: :active, accuracy: 95.2, latency: 45},
%{id: 3, name: "Vision Transformer", type: "CV", status: :loading, accuracy: 94.8, latency: 80},
%{id: 4, name: "Whisper", type: "ASR", status: :inactive, accuracy: 96.1, latency: 150}
]
end
defp get_active_tasks do
[
%{id: "task-1", type: "Inference", worker_id: 3, progress: 75},
%{id: "task-2", type: "Training", worker_id: 5, progress: 30},
%{id: "task-3", type: "Preprocessing", worker_id: 1, progress: 90}
]
end
defp format_bytes(bytes) when is_number(bytes) do
cond do
bytes >= 1_073_741_824 -> "#{Float.round(bytes / 1_073_741_824, 2)} GB"
bytes >= 1_048_576 -> "#{Float.round(bytes / 1_048_576, 2)} MB"
bytes >= 1024 -> "#{Float.round(bytes / 1024, 2)} KB"
true -> "#{bytes} B"
end
end
defp format_bytes(_), do: "0 B"
defp format_uptime(seconds) do
days = div(seconds, 86400)
hours = div(rem(seconds, 86400), 3600)
minutes = div(rem(seconds, 3600), 60)
"#{days}d #{hours}h #{minutes}m"
end
defp calculate_overall_health(checks) do
if Enum.all?(checks, fn {_, check} -> check.status == :healthy end) do
"Healthy"
else
"Degraded"
end
end
defp worker_status_color(:busy), do: "bg-green-500"
defp worker_status_color(:idle), do: "bg-yellow-500"
defp worker_status_color(:error), do: "bg-red-500"
defp worker_status_color(_), do: "bg-gray-500"
defp worker_status_badge(:busy), do: "bg-green-900 text-green-300"
defp worker_status_badge(:idle), do: "bg-yellow-900 text-yellow-300"
defp worker_status_badge(:error), do: "bg-red-900 text-red-300"
defp worker_status_badge(_), do: "bg-gray-900 text-gray-300"
defp model_status_badge(:active), do: "bg-green-900 text-green-300"
defp model_status_badge(:loading), do: "bg-yellow-900 text-yellow-300"
defp model_status_badge(:inactive), do: "bg-gray-900 text-gray-300"
defp model_status_badge(_), do: "bg-gray-900 text-gray-300"
defp health_status_color(:healthy), do: "bg-green-500"
defp health_status_color(:warning), do: "bg-yellow-500"
defp health_status_color(:critical), do: "bg-red-500"
defp health_status_color(_), do: "bg-gray-500"
defp resource_color(value, max) do
percentage = value / max * 100
cond do
percentage >= 90 -> "bg-red-500"
percentage >= 70 -> "bg-yellow-500"
true -> "bg-green-500"
end
end
end