# Monitor REST API endpoints for BEAM VM metrics and application service state. ## Overview The `Monitor` module is a stateless utility (not a GenServer) that aggregates runtime metrics from the BEAM VM and application services into maps suitable for JSON serialization. Seven REST endpoints under `/api/monitor/` are wired through `MCPServer.Router`, all protected by cookie-based authentication. Every call to an external service is wrapped in `safe_call/2` so one downed process returns `%{error: "..."}` for that section without crashing the entire response. ## Endpoints | Method | Path | Function | Description | |--------|------|----------|-------------| | GET | `/api/monitor/health` | `health/0` | Uptime, versions, node name | | GET | `/api/monitor/system` | `system/0` | Memory, processes, atoms, ports, schedulers, IO | | GET | `/api/monitor/processes` | `processes/0` | Supervisor children and counts | | GET | `/api/monitor/services` | `services/0` | WebSocket, chat, MCP clients, alarms | | GET | `/api/monitor/databases` | `databases/0` | Table names and row counts per DB | | GET | `/api/monitor/tasks` | `tasks/0` | Task counts by status | | GET | `/api/monitor` | `summary/0` | All of the above combined | ## Monitored Databases | Registered Name | Label | Purpose | |----------------|-------|---------| | `:users_db` | users | User accounts and authentication | | `:compile_log_db` | log | Compile event logs | | `:chat_db` | chat | Chat session persistence | | `:scheduler` | scheduler | Alarm and scheduled job storage | | `:a2a_db` | a2a | Agent-to-agent task storage | | `:tasks_db` | tasks | Task management storage | ## Public API ### health/0 Returns a lightweight health-check map. ```elixir Monitor.health() # => %{ # status: "ok", # uptime_seconds: 3842, # otp_release: "27", # elixir_version: "1.18.1", # node: "nonode@nohost", # timestamp: "2026-02-13T12:00:00.000000Z" # } ``` **Keys:** `status`, `uptime_seconds`, `otp_release`, `elixir_version`, `node`, `timestamp` **Sources:** `:erlang.statistics(:wall_clock)`, `System.version()`, `Node.self()`, `DateTime.utc_now()` ### system/0 Returns detailed BEAM VM metrics. ```elixir Monitor.system() # => %{ # memory: %{total: 98304000, processes: 32000000, ets: 4500000, # atom: 1200000, binary: 800000, code: 25000000, system: 66000000}, # processes: %{count: 312, limit: 1048576}, # atoms: %{count: 28500, limit: 1048577}, # ports: %{count: 12, limit: 1048576}, # schedulers: %{online: 10, total: 10}, # io: %{input_bytes: 524288000, output_bytes: 128000000} # } ``` **Sources:** `:erlang.memory/0`, `:erlang.system_info/1`, `:erlang.statistics(:io)` ### processes/0 Lists every child of `Mcp.Supervisor` with aggregate counts. ```elixir Monitor.processes() # => %{ # children: [ # %{id: "Sqler_\"users\"", pid: "#PID<0.250.0>", type: :worker, alive: true}, # %{id: "Alarm", pid: "#PID<0.260.0>", type: :worker, alive: true}, # ... # ], # counts: %{active: 17, specs: 17, supervisors: 0, workers: 17} # } ``` Pids are converted to strings via `inspect/1` for JSON serialization. ### services/0 Queries four application services for current state. Each query is independently fault-isolated. ```elixir Monitor.services() # => %{ # websocket: %{connected_users: ["bob", "alice"], ws_services: ["alarm"]}, # chat_sessions: %{count: 2, user_ids: [1, 3]}, # mcp_clients: %{count: 1, user_ids: [1]}, # alarms: %{pending_count: 3, alarms: [%{id: 123, set_at: 1707840000, delay_seconds: 300}]} # } ``` | Key | Source | Fields | |-----|--------|--------| | `websocket` | `WsHandler` | `connected_users`, `ws_services` | | `chat_sessions` | `ServerChatTracker` | `count`, `user_ids` | | `mcp_clients` | `MCPClientTracker` | `count`, `user_ids` | | `alarms` | `Alarm` | `pending_count`, `alarms` | ### databases/0 Queries all six registered Sqler instances for table names and row counts. ```elixir Monitor.databases() # => %{ # "users" => %{tables: [%{table: "users", rows: 5}, %{table: "login_attempts", rows: 42}]}, # "chat" => %{tables: [%{table: "messages", rows: 1200}]}, # "tasks" => %{tables: [%{table: "tasks", rows: 87}]}, # ... # } ``` ### tasks/0 Returns task counts broken down by status. ```elixir Monitor.tasks() # => %{ # open: 12, # in_progress: 3, # blocked: 1, # completed: 45, # due_today: 4, # overdue: 2 # } ``` | Key | TaskManager Function | Description | |-----|---------------------|-------------| | `open` | `open_tasks/0` | Status `todo` or `in_progress` | | `in_progress` | `in_progress_tasks/0` | Actively being worked on | | `blocked` | `blocked_tasks/0` | Waiting on dependencies | | `completed` | `completed_tasks/0` | Finished tasks | | `due_today` | `due_today/0` | Open tasks due within today (UTC) | | `overdue` | `overdue/0` | Past-due, not yet completed | ### summary/0 Calls all six functions above and merges the results into a single map. Powers the `GET /api/monitor` endpoint. ```elixir Monitor.summary() # => %{health: %{...}, system: %{...}, processes: %{...}, # services: %{...}, databases: %{...}, tasks: %{...}} ``` ## Internals ### safe_call/2 Private helper that wraps external service calls in `try/rescue/catch`: ```elixir defp safe_call(label, fun) do try do fun.() rescue e -> %{error: "#{label}: #{Exception.message(e)}"} catch kind, reason -> %{error: "#{label}: #{kind} - #{inspect(reason)}"} end end ``` ### format_pid/1 & format_id/1 - `format_pid/1` — converts pids via `inspect/1`, handles `:undefined` and `:restarting` - `format_id/1` — converts atom ids with `Atom.to_string/1`, tuple ids like `{Sqler, "users"}` to `"Sqler_\"users\""` ## Usage with curl ```bash # Authenticate and save session cookie curl -k -c cookies.txt -X POST https://localhost:8443/login \ -d "email=you@example.com&password=pass" # Health check curl -k -b cookies.txt https://localhost:8443/api/monitor/health # Full system overview curl -k -b cookies.txt https://localhost:8443/api/monitor # Pretty-print with jq curl -k -b cookies.txt https://localhost:8443/api/monitor/system | jq . ``` ## Dependencies | Module | Purpose | |--------|---------| | `WsHandler` | WebSocket connection data | | `ServerChatTracker` | Active chat session tracking | | `MCPClientTracker` | MCP client connection tracking | | `Alarm` | Pending alarm data | | `TaskManager` | Task status queries | | `Sqler` | Database table/count introspection | | `Mcp.Supervisor` | Supervisor child enumeration | | `Jason` | JSON encoding (in router) |