defmodule ExESDBDashboard.OperationalLive do @moduledoc """ Advanced Operational Monitoring LiveView for comprehensive system oversight. This component provides real-time monitoring of all operational aspects of the ExESDB cluster, including: - System configuration changes - Performance metrics and trends - Security events and authentication - Audit trail and compliance tracking - Alert management and notifications - Diagnostic information and debugging - Log aggregation and analysis This leverages the enhanced operational messaging patterns from ExESDB core package for consistent node tracking, precise timestamps, and comprehensive operational visibility. """ use Phoenix.LiveView require Logger # Update intervals @refresh_interval 3_000 @metrics_history_limit 100 @log_buffer_limit 200 @alert_history_limit 50 @impl true def mount(_params, _session, socket) do if connected?(socket) do subscribe_to_operational_events() schedule_refresh() end socket = socket |> assign(:page_title, "Operational Monitoring") |> assign(:active_tab, "overview") |> assign(:auto_refresh, true) |> assign(:last_updated, DateTime.utc_now()) |> assign(:operational_overview, get_initial_operational_overview()) |> assign(:performance_metrics, []) |> assign(:security_events, []) |> assign(:audit_trail, []) |> assign(:alerts, []) |> assign(:diagnostics, %{}) |> assign(:logs, []) |> assign(:config_changes, []) |> assign(:filters, %{ log_level: "all", alert_severity: "all", security_type: "all", time_range: "1h" }) {:ok, socket} end @impl true def handle_params(params, _uri, socket) do tab = Map.get(params, "tab", "overview") {:noreply, assign(socket, :active_tab, tab)} end @impl true def handle_event("switch_tab", %{"tab" => tab}, socket) do {:noreply, assign(socket, :active_tab, tab)} end @impl true def handle_event("toggle_auto_refresh", _params, socket) do auto_refresh = !socket.assigns.auto_refresh if auto_refresh and connected?(socket) do schedule_refresh() end {:noreply, assign(socket, :auto_refresh, auto_refresh)} end @impl true def handle_event("manual_refresh", _params, socket) do {:noreply, refresh_operational_data(socket)} end @impl true def handle_event("update_filter", %{"filter" => filter, "value" => value}, socket) do filters = Map.put(socket.assigns.filters, String.to_existing_atom(filter), value) {:noreply, assign(socket, :filters, filters)} end @impl true def handle_event("clear_alerts", _params, socket) do {:noreply, assign(socket, :alerts, [])} end @impl true def handle_event("export_audit", _params, socket) do # This could trigger an audit export in a real implementation {:noreply, put_flash(socket, :info, "Audit trail export requested")} end # Handle operational alert messages @impl true def handle_info({:operational_alert, alert_data}, socket) do updated_alerts = add_to_buffer(socket.assigns.alerts, alert_data, @alert_history_limit) socket = socket |> assign(:alerts, updated_alerts) |> assign(:last_updated, DateTime.utc_now()) |> update_operational_overview() {:noreply, socket} end # Handle operational metrics @impl true def handle_info({:operational_metrics, metrics_data}, socket) do updated_metrics = add_to_buffer(socket.assigns.performance_metrics, metrics_data, @metrics_history_limit) socket = socket |> assign(:performance_metrics, updated_metrics) |> assign(:last_updated, DateTime.utc_now()) |> update_operational_overview() {:noreply, socket} end # Handle security events @impl true def handle_info({:security_event, security_data}, socket) do updated_security = add_to_buffer(socket.assigns.security_events, security_data, 50) socket = socket |> assign(:security_events, updated_security) |> assign(:last_updated, DateTime.utc_now()) |> update_operational_overview() {:noreply, socket} end # Handle audit events @impl true def handle_info({:audit_event, audit_data}, socket) do updated_audit = add_to_buffer(socket.assigns.audit_trail, audit_data, 100) socket = socket |> assign(:audit_trail, updated_audit) |> assign(:last_updated, DateTime.utc_now()) |> update_operational_overview() {:noreply, socket} end # Handle diagnostic events @impl true def handle_info({:diagnostic_event, diagnostic_data}, socket) do component = diagnostic_data.component updated_diagnostics = Map.put(socket.assigns.diagnostics, component, diagnostic_data) socket = socket |> assign(:diagnostics, updated_diagnostics) |> assign(:last_updated, DateTime.utc_now()) {:noreply, socket} end # Handle log events @impl true def handle_info({:log_event, log_data}, socket) do updated_logs = add_to_buffer(socket.assigns.logs, log_data, @log_buffer_limit) socket = socket |> assign(:logs, updated_logs) |> assign(:last_updated, DateTime.utc_now()) |> update_operational_overview() {:noreply, socket} end # Handle configuration changes @impl true def handle_info({:config_change, config_data}, socket) do updated_config = add_to_buffer(socket.assigns.config_changes, config_data, 20) socket = socket |> assign(:config_changes, updated_config) |> assign(:last_updated, DateTime.utc_now()) |> update_operational_overview() {:noreply, socket} end # Handle periodic refresh @impl true def handle_info(:refresh, socket) do socket = if socket.assigns.auto_refresh do schedule_refresh() refresh_operational_data(socket) else socket end {:noreply, socket} end # Catch-all for unknown messages @impl true def handle_info(_msg, socket) do {:noreply, socket} end @impl true def render(assigns) do ~H"""
Comprehensive system oversight and analytics