2026-03-01 23:03:18 -05:00
|
|
|
|
{% extends "base.html" %}
|
|
|
|
|
|
{% block title %}Dashboard – GANDALF{% endblock %}
|
|
|
|
|
|
|
|
|
|
|
|
{% block content %}
|
|
|
|
|
|
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<!-- ── Status bar ──────────────────────────────────────────────────── -->
|
2026-03-01 23:03:18 -05:00
|
|
|
|
<div class="status-bar">
|
|
|
|
|
|
<div class="status-chips">
|
|
|
|
|
|
{% if summary.critical %}
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<span class="chip chip-critical">● {{ summary.critical }} CRITICAL</span>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
{% endif %}
|
|
|
|
|
|
{% if summary.warning %}
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<span class="chip chip-warning">● {{ summary.warning }} WARNING</span>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
{% endif %}
|
|
|
|
|
|
{% if not summary.critical and not summary.warning %}
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<span class="chip chip-ok">✔ ALL SYSTEMS NOMINAL</span>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
{% endif %}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="status-meta">
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<span class="last-check" id="last-check">{{ last_check }}</span>
|
|
|
|
|
|
<button class="btn-refresh" onclick="refreshAll()">↻ REFRESH</button>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<!-- ── Network topology + host grid ───────────────────────────────── -->
|
2026-03-01 23:03:18 -05:00
|
|
|
|
<section class="section">
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<div class="section-header">
|
|
|
|
|
|
<h2 class="section-title">Network Hosts</h2>
|
|
|
|
|
|
</div>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
|
|
|
|
|
|
<div class="topology" id="topology-diagram">
|
2026-03-14 22:06:03 -04:00
|
|
|
|
|
|
|
|
|
|
<!-- ── Tier 1: Internet ───────────────────────── -->
|
|
|
|
|
|
<div class="topo-row">
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<div class="topo-node topo-internet">
|
|
|
|
|
|
<span class="topo-icon">◈</span>
|
|
|
|
|
|
<span class="topo-label">Internet</span>
|
|
|
|
|
|
</div>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="topo-connectors single">
|
2026-03-14 22:06:03 -04:00
|
|
|
|
<div class="topo-line topo-line-labeled" data-link-label="WAN 10G SFP+"></div>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
</div>
|
2026-03-14 22:06:03 -04:00
|
|
|
|
|
|
|
|
|
|
<!-- ── Tier 2: Router ─────────────────────────── -->
|
2026-03-01 23:03:18 -05:00
|
|
|
|
<div class="topo-row">
|
2026-03-14 22:06:03 -04:00
|
|
|
|
<div class="topo-node topo-unifi">
|
2026-03-01 23:03:18 -05:00
|
|
|
|
<span class="topo-icon">⬡</span>
|
|
|
|
|
|
<span class="topo-label">UDM-Pro</span>
|
2026-03-14 22:06:03 -04:00
|
|
|
|
<span class="topo-node-sub">Dream Machine Pro · RU24</span>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="topo-connectors single">
|
|
|
|
|
|
<div class="topo-line topo-line-labeled" data-link-label="10G DAC"></div>
|
|
|
|
|
|
</div>
|
2026-03-14 22:06:03 -04:00
|
|
|
|
|
|
|
|
|
|
<!-- ── Tier 3: Switches (Agg + PoE side by side) ─ -->
|
2026-03-01 23:03:18 -05:00
|
|
|
|
<div class="topo-row">
|
2026-03-14 22:06:03 -04:00
|
|
|
|
<div class="topo-switch-tier">
|
|
|
|
|
|
<div class="topo-node topo-switch" id="topo-switch-agg">
|
|
|
|
|
|
<span class="topo-icon">⬡</span>
|
|
|
|
|
|
<span class="topo-label">USW-Agg</span>
|
|
|
|
|
|
<span class="topo-node-sub">8×10G SFP+ · RU22</span>
|
2026-03-14 22:10:17 -04:00
|
|
|
|
<span class="topo-node-sub topo-vlan-tag">VLAN90 · 10.10.90.x</span>
|
2026-03-14 22:06:03 -04:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="topo-h-link">
|
|
|
|
|
|
<div class="topo-h-link-line"></div>
|
|
|
|
|
|
<span class="topo-h-link-label">10G SFP+</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="topo-node topo-switch" id="topo-switch-poe">
|
|
|
|
|
|
<span class="topo-icon">⬡</span>
|
|
|
|
|
|
<span class="topo-label">Pro 24 PoE</span>
|
|
|
|
|
|
<span class="topo-node-sub">24×1G PoE · RU23</span>
|
2026-03-14 22:10:17 -04:00
|
|
|
|
<span class="topo-node-sub topo-vlan-tag">DHCP mgmt</span>
|
2026-03-14 22:06:03 -04:00
|
|
|
|
</div>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-03-14 22:06:03 -04:00
|
|
|
|
|
2026-03-14 22:08:48 -04:00
|
|
|
|
<!-- ── Tier 4: Hosts (all dual-homed 10G + 1G) ── -->
|
2026-03-14 22:06:03 -04:00
|
|
|
|
<div class="topo-host-tier">
|
|
|
|
|
|
<div class="topo-host-group">
|
2026-03-14 22:08:48 -04:00
|
|
|
|
|
2026-03-14 22:10:17 -04:00
|
|
|
|
<!-- 10G static VLAN90 lines from Agg (primary / Ceph) -->
|
2026-03-14 22:08:48 -04:00
|
|
|
|
<div class="topo-connectors" style="gap:20px; justify-content:center">
|
2026-03-14 22:10:17 -04:00
|
|
|
|
<div class="topo-line topo-line-labeled" data-link-label="10G SFP+"></div>
|
2026-03-14 22:06:03 -04:00
|
|
|
|
<div class="topo-line"></div>
|
|
|
|
|
|
<div class="topo-line"></div>
|
|
|
|
|
|
<div class="topo-line"></div>
|
|
|
|
|
|
<div class="topo-line"></div>
|
2026-03-14 22:08:48 -04:00
|
|
|
|
<div class="topo-line topo-line-dashed"></div>
|
2026-03-14 22:06:03 -04:00
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-03-14 22:08:48 -04:00
|
|
|
|
<!-- 1G management lines from PoE (dashed amber) -->
|
2026-03-14 22:10:17 -04:00
|
|
|
|
<!-- 1G DHCP management band from PoE switch -->
|
2026-03-14 22:08:48 -04:00
|
|
|
|
<div class="topo-mgmt-band">
|
2026-03-14 22:10:17 -04:00
|
|
|
|
<span class="topo-mgmt-label">← 1G DHCP mgmt (Pro 24 PoE) →</span>
|
2026-03-14 22:08:48 -04:00
|
|
|
|
<div class="topo-mgmt-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="topo-row topo-hosts-row">
|
2026-03-14 22:06:03 -04:00
|
|
|
|
{%- set topo_h = snapshot.hosts if snapshot.hosts else {} -%}
|
2026-03-14 22:08:48 -04:00
|
|
|
|
{%- set all_defs = [
|
2026-03-14 22:10:17 -04:00
|
|
|
|
('compute-storage-gpu-01', 'csg-01', 'RU4–12 · VLAN90', False),
|
|
|
|
|
|
('compute-storage-01', 'cs-01', 'RU14–17 · VLAN90', False),
|
|
|
|
|
|
('storage-01', 'storage-01','rack · VLAN90', False),
|
|
|
|
|
|
('monitor-01', 'monitor-01','ZimaBoard · VLAN90', False),
|
|
|
|
|
|
('monitor-02', 'monitor-02','ZimaBoard · VLAN90', False),
|
|
|
|
|
|
('large1', 'large1', 'table · VLAN90', True),
|
2026-03-14 22:06:03 -04:00
|
|
|
|
] -%}
|
2026-03-14 22:08:48 -04:00
|
|
|
|
{%- for hname, hlabel, hsub, off_rack in all_defs -%}
|
2026-03-14 22:06:03 -04:00
|
|
|
|
{%- set st = topo_h[hname].status if hname in topo_h else 'unknown' -%}
|
2026-03-14 22:08:48 -04:00
|
|
|
|
<div class="topo-node topo-host{{ ' topo-host-table' if off_rack else '' }} topo-status-{{ st }}" data-host="{{ hname }}">
|
2026-03-14 22:06:03 -04:00
|
|
|
|
<span class="topo-icon">▣</span>
|
|
|
|
|
|
<span class="topo-label">{{ hlabel }}</span>
|
|
|
|
|
|
<span class="topo-node-sub">{{ hsub }}</span>
|
|
|
|
|
|
<span class="topo-badge topo-badge-{{ st }}">{{ st if st != 'unknown' else '–' }}</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
{%- endfor -%}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-03-01 23:03:18 -05:00
|
|
|
|
</div>
|
2026-03-14 22:06:03 -04:00
|
|
|
|
</div><!-- /topo-host-tier -->
|
2026-03-01 23:03:18 -05:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Host cards -->
|
|
|
|
|
|
<div class="host-grid" id="host-grid">
|
|
|
|
|
|
{% for name, host in snapshot.hosts.items() %}
|
|
|
|
|
|
{% set suppressed = suppressions | selectattr('target_name', 'equalto', name) | list %}
|
|
|
|
|
|
<div class="host-card host-card-{{ host.status }}" data-host="{{ name }}">
|
|
|
|
|
|
<div class="host-card-header">
|
|
|
|
|
|
<div class="host-name-row">
|
|
|
|
|
|
<span class="host-status-dot dot-{{ host.status }}"></span>
|
|
|
|
|
|
<span class="host-name">{{ name }}</span>
|
|
|
|
|
|
{% if suppressed %}
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<span class="badge-suppressed" title="Suppressed">🔕</span>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
{% endif %}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="host-meta">
|
|
|
|
|
|
<span class="host-ip">{{ host.ip }}</span>
|
|
|
|
|
|
<span class="host-source source-{{ host.source }}">{{ host.source }}</span>
|
2025-01-04 01:27:49 -05:00
|
|
|
|
</div>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
</div>
|
2025-01-04 01:27:49 -05:00
|
|
|
|
|
2026-03-01 23:03:18 -05:00
|
|
|
|
{% if host.interfaces %}
|
|
|
|
|
|
<div class="iface-list">
|
|
|
|
|
|
{% for iface, state in host.interfaces.items() | sort %}
|
|
|
|
|
|
<div class="iface-row">
|
|
|
|
|
|
<span class="iface-dot dot-{{ state }}"></span>
|
|
|
|
|
|
<span class="iface-name">{{ iface }}</span>
|
|
|
|
|
|
<span class="iface-state state-{{ state }}">{{ state }}</span>
|
2025-02-07 20:58:23 -05:00
|
|
|
|
</div>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
{% endfor %}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
{% else %}
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<div class="host-ping-note">ping-only / no node_exporter</div>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
{% endif %}
|
|
|
|
|
|
|
|
|
|
|
|
<div class="host-actions">
|
|
|
|
|
|
<button class="btn-sm btn-suppress"
|
feat: inspector page, link debug enhancements, security hardening
- Add /inspector page: visual model-accurate switch chassis diagrams
(USF5P, USL8A, US24PRO, USPPDUP, USMINI), clickable port blocks
with color coding (green=up, amber=PoE, cyan=uplink, grey=down),
detail panel with stats/PoE/LLDP, LLDP-based path debug side-by-side
- Link Debug: port number badges (#N), LLDP neighbor line, PoE class/max,
collapsible host/switch panels with sessionStorage persistence
- monitor.py: collect LLDP neighbor map + PoE class/max/mode per switch
port; PulseClient uses requests.Session() for HTTP keep-alive; add
shlex.quote() around interface names (defense-in-depth)
- Security: suppress buttons use data-* attrs + delegated click handler
instead of inline onclick with Jinja2 variable interpolation; remove
| safe filter from user-controlled fields in suppressions.html;
setDuration() takes explicit el param instead of implicit event global
- db.py: thread-local connection reuse with ping(reconnect=True) to
avoid a new TCP handshake per query
- .gitignore: add config.json (contains credentials), __pycache__
- README: full rewrite covering architecture, all 4 pages, alert logic,
config reference, deployment, troubleshooting, security notes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03 15:39:48 -05:00
|
|
|
|
data-sup-type="host"
|
|
|
|
|
|
data-sup-name="{{ name }}"
|
|
|
|
|
|
data-sup-detail=""
|
2026-03-01 23:03:18 -05:00
|
|
|
|
title="Suppress alerts for this host">
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
🔕 Suppress
|
2026-03-01 23:03:18 -05:00
|
|
|
|
</button>
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<a href="{{ url_for('links_page') }}#{{ name }}"
|
|
|
|
|
|
class="btn-sm btn-secondary" style="text-decoration:none">
|
|
|
|
|
|
↗ Links
|
|
|
|
|
|
</a>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
</div>
|
2025-01-04 00:33:04 -05:00
|
|
|
|
</div>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
{% else %}
|
|
|
|
|
|
<p class="empty-state">No host data yet – monitor is initializing.</p>
|
|
|
|
|
|
{% endfor %}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<!-- ── UniFi devices ────────────────────────────────────────────────── -->
|
2026-03-01 23:03:18 -05:00
|
|
|
|
{% if snapshot.unifi %}
|
|
|
|
|
|
<section class="section">
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<div class="section-header">
|
|
|
|
|
|
<h2 class="section-title">UniFi Devices</h2>
|
|
|
|
|
|
</div>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
<div class="table-wrap">
|
|
|
|
|
|
<table class="data-table" id="unifi-table">
|
|
|
|
|
|
<thead>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<th>Status</th>
|
|
|
|
|
|
<th>Name</th>
|
|
|
|
|
|
<th>Type</th>
|
|
|
|
|
|
<th>Model</th>
|
|
|
|
|
|
<th>IP</th>
|
|
|
|
|
|
<th>Actions</th>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
</thead>
|
|
|
|
|
|
<tbody>
|
|
|
|
|
|
{% for d in snapshot.unifi %}
|
|
|
|
|
|
<tr class="{% if not d.connected %}row-critical{% endif %}">
|
|
|
|
|
|
<td>
|
|
|
|
|
|
<span class="dot-{{ 'up' if d.connected else 'down' }}"></span>
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
{{ 'ONLINE' if d.connected else 'OFFLINE' }}
|
2026-03-01 23:03:18 -05:00
|
|
|
|
</td>
|
|
|
|
|
|
<td><strong>{{ d.name }}</strong></td>
|
|
|
|
|
|
<td>{{ d.type }}</td>
|
|
|
|
|
|
<td>{{ d.model }}</td>
|
|
|
|
|
|
<td>{{ d.ip }}</td>
|
|
|
|
|
|
<td>
|
|
|
|
|
|
{% if not d.connected %}
|
|
|
|
|
|
<button class="btn-sm btn-suppress"
|
feat: inspector page, link debug enhancements, security hardening
- Add /inspector page: visual model-accurate switch chassis diagrams
(USF5P, USL8A, US24PRO, USPPDUP, USMINI), clickable port blocks
with color coding (green=up, amber=PoE, cyan=uplink, grey=down),
detail panel with stats/PoE/LLDP, LLDP-based path debug side-by-side
- Link Debug: port number badges (#N), LLDP neighbor line, PoE class/max,
collapsible host/switch panels with sessionStorage persistence
- monitor.py: collect LLDP neighbor map + PoE class/max/mode per switch
port; PulseClient uses requests.Session() for HTTP keep-alive; add
shlex.quote() around interface names (defense-in-depth)
- Security: suppress buttons use data-* attrs + delegated click handler
instead of inline onclick with Jinja2 variable interpolation; remove
| safe filter from user-controlled fields in suppressions.html;
setDuration() takes explicit el param instead of implicit event global
- db.py: thread-local connection reuse with ping(reconnect=True) to
avoid a new TCP handshake per query
- .gitignore: add config.json (contains credentials), __pycache__
- README: full rewrite covering architecture, all 4 pages, alert logic,
config reference, deployment, troubleshooting, security notes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03 15:39:48 -05:00
|
|
|
|
data-sup-type="unifi_device"
|
|
|
|
|
|
data-sup-name="{{ d.name }}"
|
|
|
|
|
|
data-sup-detail="">
|
2026-03-01 23:03:18 -05:00
|
|
|
|
🔕 Suppress
|
|
|
|
|
|
</button>
|
|
|
|
|
|
{% endif %}
|
|
|
|
|
|
</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
{% endfor %}
|
|
|
|
|
|
</tbody>
|
|
|
|
|
|
</table>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
{% endif %}
|
|
|
|
|
|
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<!-- ── Active alerts ───────────────────────────────────────────────── -->
|
2026-03-01 23:03:18 -05:00
|
|
|
|
<section class="section">
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<div class="section-header">
|
|
|
|
|
|
<h2 class="section-title">Active Alerts</h2>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
{% if summary.critical or summary.warning %}
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<span class="section-badge">{{ (summary.critical or 0) + (summary.warning or 0) }}</span>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
{% endif %}
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
</div>
|
|
|
|
|
|
<div id="events-table-wrap">
|
2026-03-01 23:03:18 -05:00
|
|
|
|
{% if events %}
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<div class="table-wrap">
|
|
|
|
|
|
<table class="data-table" id="events-table">
|
|
|
|
|
|
<thead>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<th>Sev</th>
|
|
|
|
|
|
<th>Type</th>
|
|
|
|
|
|
<th>Target</th>
|
|
|
|
|
|
<th>Detail</th>
|
|
|
|
|
|
<th>Description</th>
|
|
|
|
|
|
<th>First Seen</th>
|
2026-03-14 21:46:11 -04:00
|
|
|
|
<th>Last Seen</th>
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<th>Failures</th>
|
|
|
|
|
|
<th>Ticket</th>
|
|
|
|
|
|
<th>Actions</th>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
</thead>
|
|
|
|
|
|
<tbody>
|
|
|
|
|
|
{% for e in events %}
|
|
|
|
|
|
{% if e.severity != 'info' %}
|
|
|
|
|
|
<tr class="row-{{ e.severity }}">
|
|
|
|
|
|
<td><span class="badge badge-{{ e.severity }}">{{ e.severity }}</span></td>
|
|
|
|
|
|
<td>{{ e.event_type | replace('_', ' ') }}</td>
|
|
|
|
|
|
<td><strong>{{ e.target_name }}</strong></td>
|
|
|
|
|
|
<td>{{ e.target_detail or '–' }}</td>
|
2026-03-13 14:36:55 -04:00
|
|
|
|
<td class="desc-cell" title="{{ e.description | e }}">{{ e.description | truncate(60) }}</td>
|
2026-03-14 21:46:11 -04:00
|
|
|
|
<td class="ts-cell" title="{{ e.first_seen }}">
|
|
|
|
|
|
<span class="event-age" data-ts="{{ e.first_seen }}">{{ e.first_seen }}</span>
|
|
|
|
|
|
</td>
|
|
|
|
|
|
<td class="ts-cell" title="{{ e.last_seen }}">
|
|
|
|
|
|
<span class="event-age" data-ts="{{ e.last_seen }}">{{ e.last_seen }}</span>
|
|
|
|
|
|
</td>
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<td>{{ e.consecutive_failures }}</td>
|
|
|
|
|
|
<td>
|
|
|
|
|
|
{% if e.ticket_id %}
|
2026-03-14 14:31:57 -04:00
|
|
|
|
<a href="{{ config.ticket_api.web_url }}{{ e.ticket_id }}" target="_blank"
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
class="ticket-link">#{{ e.ticket_id }}</a>
|
|
|
|
|
|
{% else %}–{% endif %}
|
|
|
|
|
|
</td>
|
|
|
|
|
|
<td>
|
|
|
|
|
|
<button class="btn-sm btn-suppress"
|
feat: inspector page, link debug enhancements, security hardening
- Add /inspector page: visual model-accurate switch chassis diagrams
(USF5P, USL8A, US24PRO, USPPDUP, USMINI), clickable port blocks
with color coding (green=up, amber=PoE, cyan=uplink, grey=down),
detail panel with stats/PoE/LLDP, LLDP-based path debug side-by-side
- Link Debug: port number badges (#N), LLDP neighbor line, PoE class/max,
collapsible host/switch panels with sessionStorage persistence
- monitor.py: collect LLDP neighbor map + PoE class/max/mode per switch
port; PulseClient uses requests.Session() for HTTP keep-alive; add
shlex.quote() around interface names (defense-in-depth)
- Security: suppress buttons use data-* attrs + delegated click handler
instead of inline onclick with Jinja2 variable interpolation; remove
| safe filter from user-controlled fields in suppressions.html;
setDuration() takes explicit el param instead of implicit event global
- db.py: thread-local connection reuse with ping(reconnect=True) to
avoid a new TCP handshake per query
- .gitignore: add config.json (contains credentials), __pycache__
- README: full rewrite covering architecture, all 4 pages, alert logic,
config reference, deployment, troubleshooting, security notes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03 15:39:48 -05:00
|
|
|
|
data-sup-type="{{ 'unifi_device' if e.event_type == 'unifi_device_offline' else 'interface' if e.event_type == 'interface_down' else 'host' }}"
|
|
|
|
|
|
data-sup-name="{{ e.target_name }}"
|
|
|
|
|
|
data-sup-detail="{{ e.target_detail or '' }}"
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
title="Suppress">🔕</button>
|
|
|
|
|
|
</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
{% endif %}
|
|
|
|
|
|
{% else %}
|
2026-03-14 21:46:11 -04:00
|
|
|
|
<tr><td colspan="10" class="empty-state">No active alerts ✔</td></tr>
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
{% endfor %}
|
|
|
|
|
|
</tbody>
|
|
|
|
|
|
</table>
|
|
|
|
|
|
</div>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
{% else %}
|
|
|
|
|
|
<p class="empty-state">No active alerts ✔</p>
|
|
|
|
|
|
{% endif %}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
feat: link health summary, recently resolved panel, event duration
- dashboard: pass recent_resolved (last 24h, limit 10) to index template;
render "Recently Resolved" section showing type, target, resolved time,
and calculated duration (first_seen → resolved_at)
- dashboard: event-age spans now also update via setInterval; duration
shown for resolved events (e.g. "2h 15m")
- links page: link health summary panel shows server iface count,
error/flap counts, switch port up/down, PoE total draw/capacity bar;
only shows problematic stats if non-zero; shows "All OK ✔" when clean
- style.css: new classes for summary panel, resolved row/badge
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 21:48:40 -04:00
|
|
|
|
<!-- ── Recently Resolved (last 24h) ───────────────────────────────── -->
|
|
|
|
|
|
{% if recent_resolved %}
|
|
|
|
|
|
<section class="section">
|
|
|
|
|
|
<div class="section-header">
|
|
|
|
|
|
<h2 class="section-title">Recently Resolved</h2>
|
|
|
|
|
|
<span class="section-badge section-badge-resolved">{{ recent_resolved | length }} in last 24h</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="table-wrap">
|
|
|
|
|
|
<table class="data-table">
|
|
|
|
|
|
<thead>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<th>Sev</th>
|
|
|
|
|
|
<th>Type</th>
|
|
|
|
|
|
<th>Target</th>
|
|
|
|
|
|
<th>Detail</th>
|
|
|
|
|
|
<th>Resolved</th>
|
|
|
|
|
|
<th>Duration</th>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
</thead>
|
|
|
|
|
|
<tbody>
|
|
|
|
|
|
{% for e in recent_resolved %}
|
|
|
|
|
|
<tr class="row-resolved">
|
|
|
|
|
|
<td><span class="badge badge-resolved">{{ e.severity }}</span></td>
|
|
|
|
|
|
<td>{{ e.event_type | replace('_', ' ') }}</td>
|
|
|
|
|
|
<td><strong>{{ e.target_name }}</strong></td>
|
|
|
|
|
|
<td>{{ e.target_detail or '–' }}</td>
|
|
|
|
|
|
<td class="ts-cell">
|
|
|
|
|
|
<span class="event-age" data-ts="{{ e.resolved_at }}">{{ e.resolved_at }}</span>
|
|
|
|
|
|
</td>
|
|
|
|
|
|
<td class="ts-cell event-duration" data-first="{{ e.first_seen }}" data-resolved="{{ e.resolved_at }}">–</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
{% endfor %}
|
|
|
|
|
|
</tbody>
|
|
|
|
|
|
</table>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
{% endif %}
|
|
|
|
|
|
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<!-- ── Quick-suppress modal ─────────────────────────────────────────── -->
|
2026-03-01 23:03:18 -05:00
|
|
|
|
<div id="suppress-modal" class="modal-overlay" style="display:none">
|
|
|
|
|
|
<div class="modal">
|
|
|
|
|
|
<div class="modal-header">
|
|
|
|
|
|
<h3>Suppress Alert</h3>
|
|
|
|
|
|
<button class="modal-close" onclick="closeSuppressModal()">✕</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<form id="suppress-form" onsubmit="submitSuppress(event)">
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<div class="form-group" style="margin-bottom:10px">
|
2026-03-01 23:03:18 -05:00
|
|
|
|
<label>Target Type</label>
|
|
|
|
|
|
<select id="sup-type" name="target_type" onchange="updateSuppressForm()">
|
|
|
|
|
|
<option value="host">Host (all interfaces)</option>
|
|
|
|
|
|
<option value="interface">Specific Interface</option>
|
|
|
|
|
|
<option value="unifi_device">UniFi Device</option>
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<option value="all">Global Maintenance</option>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
</select>
|
|
|
|
|
|
</div>
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<div class="form-group" id="sup-name-group" style="margin-bottom:10px">
|
2026-03-01 23:03:18 -05:00
|
|
|
|
<label>Target Name</label>
|
|
|
|
|
|
<input type="text" id="sup-name" name="target_name" placeholder="e.g. large1">
|
|
|
|
|
|
</div>
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<div class="form-group" id="sup-detail-group" style="margin-bottom:10px;display:none">
|
|
|
|
|
|
<label>Interface <span class="form-hint">(interface type only)</span></label>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
<input type="text" id="sup-detail" name="target_detail" placeholder="e.g. enp35s0">
|
|
|
|
|
|
</div>
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<div class="form-group" style="margin-bottom:10px">
|
2026-03-01 23:03:18 -05:00
|
|
|
|
<label>Reason <span class="required">*</span></label>
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<input type="text" id="sup-reason" name="reason"
|
|
|
|
|
|
placeholder="e.g. Planned switch reboot" required>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
</div>
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<div class="form-group" style="margin-bottom:0">
|
2026-03-01 23:03:18 -05:00
|
|
|
|
<label>Duration</label>
|
|
|
|
|
|
<div class="duration-pills">
|
feat: inspector page, link debug enhancements, security hardening
- Add /inspector page: visual model-accurate switch chassis diagrams
(USF5P, USL8A, US24PRO, USPPDUP, USMINI), clickable port blocks
with color coding (green=up, amber=PoE, cyan=uplink, grey=down),
detail panel with stats/PoE/LLDP, LLDP-based path debug side-by-side
- Link Debug: port number badges (#N), LLDP neighbor line, PoE class/max,
collapsible host/switch panels with sessionStorage persistence
- monitor.py: collect LLDP neighbor map + PoE class/max/mode per switch
port; PulseClient uses requests.Session() for HTTP keep-alive; add
shlex.quote() around interface names (defense-in-depth)
- Security: suppress buttons use data-* attrs + delegated click handler
instead of inline onclick with Jinja2 variable interpolation; remove
| safe filter from user-controlled fields in suppressions.html;
setDuration() takes explicit el param instead of implicit event global
- db.py: thread-local connection reuse with ping(reconnect=True) to
avoid a new TCP handshake per query
- .gitignore: add config.json (contains credentials), __pycache__
- README: full rewrite covering architecture, all 4 pages, alert logic,
config reference, deployment, troubleshooting, security notes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-03 15:39:48 -05:00
|
|
|
|
<button type="button" class="pill" onclick="setDuration(30, this)">30 min</button>
|
|
|
|
|
|
<button type="button" class="pill" onclick="setDuration(60, this)">1 hr</button>
|
|
|
|
|
|
<button type="button" class="pill" onclick="setDuration(240, this)">4 hr</button>
|
|
|
|
|
|
<button type="button" class="pill" onclick="setDuration(480, this)">8 hr</button>
|
|
|
|
|
|
<button type="button" class="pill pill-manual active" onclick="setDuration(null, this)">Manual ∞</button>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
</div>
|
|
|
|
|
|
<input type="hidden" id="sup-expires" name="expires_minutes" value="">
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<div class="form-hint" id="duration-hint">Persists until manually removed.</div>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="modal-actions">
|
|
|
|
|
|
<button type="button" class="btn btn-secondary" onclick="closeSuppressModal()">Cancel</button>
|
feat: terminal aesthetic rewrite + link debug page
- Full dark terminal aesthetic (Pulse/TinkerTickets style):
- #0a0a0a background, #00ff41 green, #ffb000 amber, #00ffff cyan
- CRT scanline overlay, phosphor glow, ASCII corner pseudoelements
- Bracket-notation badges [CRITICAL], monospace font throughout
- style.css, base.html, index.html, suppressions.html all rewritten
- New Link Debug page (/links, /api/links):
- Per-host, per-interface cards with speed/duplex/port type/auto-neg
- Traffic bars (TX cyan, RX green) with rate labels
- Error/drop counters, carrier change history
- SFP/DOM optical panel: vendor, temp, voltage, bias, TX/RX power dBm bars
- RX-TX delta shown; color-coded warn/crit thresholds
- Auto-refresh every 60s, anchor-jump to #hostname
- LinkStatsCollector in monitor.py:
- SSHes to each host (one connection, all ifaces batched)
- Parses ethtool + ethtool -m (SFP DOM) output
- Merges with Prometheus traffic/error/carrier metrics
- Stores as link_stats in monitor_state table
- config.json: added ssh section for ethtool collection
- app.js: terminal chip style consistency (uppercase, ● bullet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 12:43:11 -05:00
|
|
|
|
<button type="submit" class="btn btn-primary">Apply</button>
|
2026-03-01 23:03:18 -05:00
|
|
|
|
</div>
|
|
|
|
|
|
</form>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{% endblock %}
|
|
|
|
|
|
|
|
|
|
|
|
{% block scripts %}
|
|
|
|
|
|
<script>
|
|
|
|
|
|
setInterval(refreshAll, 30000);
|
2026-03-14 21:46:11 -04:00
|
|
|
|
|
|
|
|
|
|
// ── Relative time display for event age cells ──────────────────
|
|
|
|
|
|
function fmtRelTime(tsStr) {
|
|
|
|
|
|
if (!tsStr) return '–';
|
|
|
|
|
|
const d = new Date(tsStr.replace(' UTC', 'Z').replace(' ', 'T'));
|
|
|
|
|
|
if (isNaN(d)) return tsStr;
|
|
|
|
|
|
const secs = Math.floor((Date.now() - d) / 1000);
|
|
|
|
|
|
if (secs < 60) return `${secs}s ago`;
|
|
|
|
|
|
if (secs < 3600) return `${Math.floor(secs/60)}m ago`;
|
|
|
|
|
|
if (secs < 86400) return `${Math.floor(secs/3600)}h ago`;
|
|
|
|
|
|
return `${Math.floor(secs/86400)}d ago`;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function updateEventAges() {
|
|
|
|
|
|
document.querySelectorAll('.event-age[data-ts]').forEach(el => {
|
|
|
|
|
|
el.textContent = fmtRelTime(el.dataset.ts);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
updateEventAges();
|
|
|
|
|
|
setInterval(updateEventAges, 60000);
|
feat: link health summary, recently resolved panel, event duration
- dashboard: pass recent_resolved (last 24h, limit 10) to index template;
render "Recently Resolved" section showing type, target, resolved time,
and calculated duration (first_seen → resolved_at)
- dashboard: event-age spans now also update via setInterval; duration
shown for resolved events (e.g. "2h 15m")
- links page: link health summary panel shows server iface count,
error/flap counts, switch port up/down, PoE total draw/capacity bar;
only shows problematic stats if non-zero; shows "All OK ✔" when clean
- style.css: new classes for summary panel, resolved row/badge
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 21:48:40 -04:00
|
|
|
|
|
|
|
|
|
|
// ── Event duration (resolved_at - first_seen) ──────────────────
|
|
|
|
|
|
function fmtDuration(firstTs, resolvedTs) {
|
|
|
|
|
|
if (!firstTs || !resolvedTs) return '–';
|
|
|
|
|
|
const parse = s => new Date(s.replace(' UTC', 'Z').replace(' ', 'T'));
|
|
|
|
|
|
const secs = Math.floor((parse(resolvedTs) - parse(firstTs)) / 1000);
|
|
|
|
|
|
if (secs < 0) return '–';
|
|
|
|
|
|
if (secs < 60) return `${secs}s`;
|
|
|
|
|
|
if (secs < 3600) return `${Math.floor(secs/60)}m`;
|
|
|
|
|
|
if (secs < 86400) return `${Math.floor(secs/3600)}h ${Math.floor((secs%3600)/60)}m`;
|
|
|
|
|
|
return `${Math.floor(secs/86400)}d`;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
document.querySelectorAll('.event-duration[data-first][data-resolved]').forEach(el => {
|
|
|
|
|
|
el.textContent = fmtDuration(el.dataset.first, el.dataset.resolved);
|
|
|
|
|
|
});
|
2026-03-01 23:03:18 -05:00
|
|
|
|
</script>
|
|
|
|
|
|
{% endblock %}
|