The dashboard's host widgets took 18-60 s. Every "latest reading" query (hosts overview, host-agent fleet, host page, vitals, SNMP, MCP get_host) searched plugin_metrics for the newest row per metric. Postgres has no skip scan, so each one read every raw sample in the 7-day window. - plugin_metric_latest: one row per (source, resource, metric). record_metrics upserts it in the same transaction, moving forward only and in sorted key order. Migration 0030 seeds it by stepping the existing index. - Retention drops a latest row once its sample leaves the raw window, so a resource that stopped reporting disappears when its history does, as before. Renames carry it along. - A quiet host keeps its last values, marked stale. A time-bounded query would have shown it as missing. - Vitals sparklines span the 6 h they claim, averaged in SQL to ~120 points, instead of fetching 6 h raw and drawing the last 120 samples. - Dashboard and share-view cells: "Loading…" until the first answer; a 20 s deadline per fetch; "Couldn't load (why)" with Retry now and an automatic retry for cells that don't poll; "as of HH:MM" in the header, and "couldn't refresh · as of" when a refresh fails over shown data. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
162 lines
7.1 KiB
Markdown
162 lines
7.1 KiB
Markdown
# Code Map
|
|
|
|
Quick reference for where key functions, models, and entry points live in the codebase.
|
|
|
|
---
|
|
|
|
## Application Bootstrap
|
|
|
|
| What | File | Function / Class |
|
|
|---|---|---|
|
|
| App factory | `steward/app.py` | `create_app()` |
|
|
| CLI entry point | `steward/cli.py` | `main()` |
|
|
| Bootstrap config loading | `steward/config.py` | `load_bootstrap()` |
|
|
| Secret key resolution | `steward/config.py` | `_resolve_secret_key()` |
|
|
| DB engine init | `steward/database.py` | `init_db()` |
|
|
| Core migrations | `steward/core/migration_runner.py` | `run_core_migrations()` |
|
|
| Plugin migrations | `steward/core/migration_runner.py` | `run_plugin_migrations()` |
|
|
| Core task registration | `steward/app.py` | `_register_core_tasks()` |
|
|
| Scheduler loop | `steward/core/scheduler.py` | `start_scheduler()` |
|
|
|
|
---
|
|
|
|
## Settings System
|
|
|
|
| What | File | Function |
|
|
|---|---|---|
|
|
| All defaults | `steward/core/settings.py` | `DEFAULTS` dict |
|
|
| Read a setting | `steward/core/settings.py` | `get_setting(session, key)` |
|
|
| Write a setting | `steward/core/settings.py` | `set_setting(session, key, value)` |
|
|
| Read all settings | `steward/core/settings.py` | `get_all_settings(session)` |
|
|
| Sync load at startup | `steward/core/settings.py` | `load_settings_sync(db_url)` |
|
|
| Extract SMTP dict | `steward/core/settings.py` | `to_smtp_cfg(settings)` |
|
|
| Extract webhook dict | `steward/core/settings.py` | `to_webhook_cfg(settings)` |
|
|
| Extract Ansible dict | `steward/core/settings.py` | `to_ansible_cfg(settings)` |
|
|
| Extract plugins dict | `steward/core/settings.py` | `to_plugins_cfg(settings)` |
|
|
|
|
---
|
|
|
|
## Plugin System
|
|
|
|
| What | File | Function |
|
|
|---|---|---|
|
|
| Plugin loading | `steward/core/plugin_manager.py` | `load_plugins(app)` |
|
|
| ScheduledTask dataclass | `steward/core/scheduler.py` | `ScheduledTask` |
|
|
| Task runner | `steward/core/scheduler.py` | `start_scheduler(tasks)` |
|
|
|
|
---
|
|
|
|
## Alert Pipeline
|
|
|
|
| What | File | Function |
|
|
|---|---|---|
|
|
| Write metric + evaluate alerts | `steward/core/alerts.py` | `record_metric(session, source_module, resource_name, metric_name, value)` |
|
|
| Init alert pipeline | `steward/core/alerts.py` | `init_alerts(app)` |
|
|
| Rule evaluation | `steward/core/alerts.py` | `_evaluate_rule()` (internal) |
|
|
| Notification dispatch | `steward/core/alerts.py` | `_dispatch_notification()` (internal) |
|
|
| Email + webhook send | `steward/core/notifications.py` | `dispatch_notifications()` |
|
|
|
|
---
|
|
|
|
## Monitors
|
|
|
|
| What | File | Function |
|
|
|---|---|---|
|
|
| Ping a host | `steward/monitors/ping.py` | `ping_check(host, session)` |
|
|
| DNS check a host | `steward/monitors/dns.py` | `dns_check(host, session)` |
|
|
| Data cleanup | `steward/core/cleanup.py` | `run_cleanup(app)` |
|
|
|
|
---
|
|
|
|
## Auth
|
|
|
|
| What | File | Function / Class |
|
|
|---|---|---|
|
|
| Role-based access decorator | `steward/auth/middleware.py` | `@require_role(UserRole.X)` |
|
|
| Login / session handling | `steward/auth/middleware.py` | `login_user()`, `logout_user()` |
|
|
| User count (for first-run) | `steward/auth/middleware.py` | `get_user_count(app)` |
|
|
|
|
---
|
|
|
|
## Data Models
|
|
|
|
| Model | File | Table |
|
|
|---|---|---|
|
|
| `Host` | `steward/models/hosts.py` | `hosts` |
|
|
| `PingResult` | `steward/models/monitors.py` | `ping_results` |
|
|
| `DnsResult` | `steward/models/monitors.py` | `dns_results` |
|
|
| `AlertRule` | `steward/models/alerts.py` | `alert_rules` |
|
|
| `AlertState` | `steward/models/alerts.py` | `alert_states` |
|
|
| `AlertEvent` | `steward/models/alerts.py` | `alert_events` |
|
|
| `PluginMetric` | `steward/models/metrics.py` | `plugin_metrics` |
|
|
| `PluginMetricLatest` | `steward/models/metrics.py` | `plugin_metric_latest` |
|
|
| `AnsibleRun` | `steward/models/ansible.py` | `ansible_runs` |
|
|
| `User` | `steward/models/users.py` | `users` |
|
|
| `AppSetting` | `steward/models/settings.py` | `app_settings` |
|
|
| `TraefikMetric` | `plugins/traefik/models.py` | `traefik_metrics` |
|
|
| SQLAlchemy `Base` | `steward/models/base.py` | (shared declarative base) |
|
|
|
|
---
|
|
|
|
## HTTP Routes
|
|
|
|
| URL pattern | Blueprint | File |
|
|
|---|---|---|
|
|
| `/` (dashboard) | `dashboard_bp` | `steward/dashboard/routes.py` |
|
|
| `/auth/login`, `/auth/logout` | `auth_bp` | `steward/auth/routes.py` |
|
|
| `/hosts/` | `hosts_bp` | `steward/hosts/routes.py` |
|
|
| `/ping/`, `/ping/rows`, `/ping/settings` | `ping_bp` | `steward/ping/routes.py` |
|
|
| `/dns/`, `/dns/rows` | `dns_bp` | `steward/dns/routes.py` |
|
|
| `/alerts/` | `alerts_bp` | `steward/alerts/routes.py` |
|
|
| `/ansible/` | `ansible_bp` | `steward/ansible/routes.py` |
|
|
| `/settings/` | `settings_bp` | `steward/settings/routes.py` |
|
|
| `/plugins/traefik/`, `/plugins/traefik/widget` | `traefik_bp` | `plugins/traefik/routes.py` |
|
|
| `/health` | (inline) | `steward/app.py` |
|
|
|
|
---
|
|
|
|
## Templates
|
|
|
|
| Template | Purpose |
|
|
|---|---|
|
|
| `steward/templates/base.html` | Layout, navigation, full CSS design system |
|
|
| `steward/templates/dashboard/index.html` | Dashboard with stat strip and widget grid |
|
|
| `steward/templates/ping/rows.html` | HTMX fragment: ping pill rows (shared by dashboard and /ping/) |
|
|
| `steward/templates/ping/index.html` | Full /ping/ page |
|
|
| `steward/templates/dns/rows.html` | HTMX fragment: DNS status rows |
|
|
| `steward/templates/dns/index.html` | Full /dns/ page |
|
|
| `plugins/traefik/templates/traefik/widget.html` | HTMX fragment: Traefik dashboard widget |
|
|
| `plugins/traefik/templates/traefik/index.html` | Full Traefik detail page |
|
|
|
|
---
|
|
|
|
## Migrations
|
|
|
|
| Location | Covers |
|
|
|---|---|
|
|
| `steward/migrations/versions/` | Core schema (hosts, users, monitors, alerts, app_settings) |
|
|
| `plugins/traefik/migrations/versions/` | `traefik_metrics` table |
|
|
| `alembic.ini` | Alembic config; `version_locations` lists all migration directories |
|
|
|
|
---
|
|
|
|
## MCP server and API tokens
|
|
|
|
| What | File | Function / Class |
|
|
|---|---|---|
|
|
| Mount `/mcp` (ASGI dispatch, bearer auth, DB gate) | `steward/mcp/server.py` | `mount_mcp(app)` |
|
|
| Server, role registry, refusals | `steward/mcp/server.py` | `StewardMCPServer`, `register_tool()`, `refusal()` |
|
|
| Plugin tools and overview findings | `steward/mcp/server.py` | `register_plugin(name, module)` |
|
|
| Caller and app inside a tool | `steward/mcp/_context.py` | `current_caller()`, `mcp_app()` |
|
|
| Core tool modules | `steward/mcp/tools/` | `register_all()`; one module per area |
|
|
| Response conventions | `steward/mcp/tools/_shape.py` | `iso`, `age_s`, `bounded`, `lookback`, `summarize`, `pick` |
|
|
| Audit a write as "<user> via MCP" | `steward/mcp/tools/_audit.py` | `audit_mcp()` |
|
|
| "What is wrong now" | `steward/mcp/tools/overview.py` | `get_overview()` |
|
|
| Playbooks, runs, schedules, alert actions | `steward/mcp/tools/automation.py` | `run_playbook()`, `wait_for_run()`, … |
|
|
| Monitor validation (forms and tools) | `steward/monitors/service.py` | `monitor_fields()`, `build_config()` |
|
|
| Alert rule / window validation | `steward/alerts/service.py` | `rule_fields()`, `window_fields()`, `acknowledge()` |
|
|
| Docker and host-agent tools | `plugins/docker/mcp_tools.py`, `plugins/host_agent/mcp_tools.py` | `register_tools()`, `mcp_overview()` |
|
|
| Token model | `steward/models/api_tokens.py` | `ApiToken` |
|
|
| Mint, resolve, revoke tokens | `steward/core/api_tokens.py` | `create_token()`, `resolve_token()`, `revoke_token()` |
|
|
| Token management page and connect card | `steward/ai_access/routes.py`, `steward/templates/ai_access/` | `ai_access_bp` |
|