Sweeps README, docs/, example configs, code docstrings, report and notification subject lines, plugin catalog URL default, and stray comments in Dockerfile/entrypoint.sh/.gitignore. Adds a legacy note to docs/core/configuration.md explaining the FABLEDSCRYER_* fallback. docker-compose DB credentials intentionally left as fabledscryer to preserve the existing pgdata volume.
4.1 KiB
Core Monitors
Roundtable ships two built-in monitors: Ping and DNS. Both run as asyncio scheduled tasks on the same event loop as the web server, with no separate processes.
Ping Monitor
Source: roundtable/monitors/ping.py
Scheduler task: ping_monitor in roundtable/app.py
Interval: monitors.poll_interval_seconds (default 60s), runs on startup
How It Works
On each tick, the scheduler fetches all hosts with ping_enabled = true and calls ping_check(host, session) for each.
ping_check() probes the host using:
- ICMP if
host.probe_type == "icmp"— uses the systempingbinary (/bin/pingor equivalent). Requiresiputils-pingin Docker. - TCP if
host.probe_type == "tcp"(default) — attempts an async TCP connection tohost.address:host.probe_port(default port 80).
Each probe writes a PingResult row and calls record_metric():
source_module |
resource_name |
metric_name |
value |
|---|---|---|---|
ping |
host.name |
response_time_ms |
measured latency, or 0.0 if down |
ping |
host.name |
up |
1.0 if up, 0.0 if down |
Alert rule note: Because response_time_ms is recorded as 0.0 when a host is down, a latency rule (e.g. response_time_ms > 500) will not fire on complete outages. Use a separate rule on up == 0.0 to detect host down events.
Data Model
ping_results table (defined in roundtable/models/monitors.py):
| Column | Type | Description |
|---|---|---|
id |
UUID | Primary key |
host_id |
FK → hosts | |
probed_at |
timestamp UTC | When the probe ran |
status |
enum up/down |
Result |
response_time_ms |
float | Null if down |
Old rows are pruned by the data_cleanup task (default: 90 days).
UI
- Dashboard widget — live-updating via HTMX polling (
/ping/rows) /ping/page — full page with 30-pill history per host and threshold settings form- Hosts list — shows latest ping status dot and latency
DNS Monitor
Source: roundtable/monitors/dns.py
Scheduler task: dns_monitor in roundtable/app.py
Interval: monitors.poll_interval_seconds (default 60s), runs on startup
How It Works
On each tick, the scheduler fetches all hosts with dns_enabled = true and calls dns_check(host, session) for each.
dns_check() resolves host.address using the system resolver. If host.dns_expected_ip is set, the check passes only if at least one returned A/AAAA record exactly matches that string. If dns_expected_ip is null, any successful resolution counts as a pass.
Each check writes a DnsResult row and calls record_metric():
source_module |
resource_name |
metric_name |
value |
|---|---|---|---|
dns |
host.name |
resolved |
1.0 if resolved, 0.0 if failed |
dns |
host.name |
ip_changed |
1.0 if IP changed from last successful result, 0.0 otherwise |
Data Model
dns_results table (defined in roundtable/models/monitors.py):
| Column | Type | Description |
|---|---|---|
id |
UUID | Primary key |
host_id |
FK → hosts | |
resolved_at |
timestamp UTC | When the check ran |
status |
enum resolved/failed |
Result |
resolved_ip |
str | First returned A/AAAA record; null if failed |
ip_changed is computed by comparing resolved_ip of the current result against the most recent prior resolved result for the same host.
UI
- Dashboard widget — live-updating via HTMX polling (
/dns/rows) /dns/page — full page showing all DNS-enabled hosts with status, resolved IP, and timestamp- Hosts list — shows latest DNS status dot
Host Configuration
Hosts are managed at /hosts/. Both monitors are configured per-host:
| Field | Description |
|---|---|
ping_enabled |
Enable ping probing for this host |
probe_type |
tcp (default) or icmp |
probe_port |
TCP port to connect to (default 80; ignored for ICMP) |
dns_enabled |
Enable DNS resolution checks |
dns_expected_ip |
If set, the resolved IP must match this string exactly |
poll_interval_seconds |
Per-host override for the global poll interval; null uses global |