diff --git a/app.py b/app.py index df59a52..ef9257d 100644 --- a/app.py +++ b/app.py @@ -29,6 +29,19 @@ app = Flask(__name__) _cfg = None + +@app.context_processor +def inject_config(): + """Inject safe config values into all templates.""" + cfg = _config() + return { + 'config': { + 'ticket_api': { + 'web_url': cfg.get('ticket_api', {}).get('web_url', 'http://t.lotusguild.org/ticket/'), + } + } + } + # In-memory diagnostic job store { job_id: { status, result, created_at } } _diag_jobs: dict = {} _diag_lock = threading.Lock() diff --git a/monitor.py b/monitor.py index dab544e..95c80e3 100644 --- a/monitor.py +++ b/monitor.py @@ -641,6 +641,7 @@ class NetworkMonitor: self.poll_interval = mon.get('poll_interval', 120) self.fail_thresh = mon.get('failure_threshold', 2) self.cluster_thresh = mon.get('cluster_threshold', 3) + self.cluster_name = mon.get('cluster_name', CLUSTER_NAME) # Build Prometheus instance → hostname lookup self._instance_map: Dict[str, str] = { @@ -706,13 +707,13 @@ class NetworkMonitor: sup = db.check_suppressed(suppressions, 'all', '') event_id, is_new, consec = db.upsert_event( 'cluster_network_issue', 'critical', 'prometheus', - CLUSTER_NAME, '', + self.cluster_name, '', f'{len(hosts_with_regression)} hosts reporting simultaneous interface failures: ' f'{", ".join(hosts_with_regression)}', ) if not sup and is_new: title = ( - f'[{CLUSTER_NAME}][auto][production][issue][network][cluster-wide] ' + f'[{self.cluster_name}][auto][production][issue][network][cluster-wide] ' f'Multiple hosts reporting interface failures' ) desc = ( @@ -728,7 +729,7 @@ class NetworkMonitor: if tid: db.set_ticket_id(event_id, tid) else: - db.resolve_event('cluster_network_issue', CLUSTER_NAME, '') + db.resolve_event('cluster_network_issue', self.cluster_name, '') def _ticket_interface( self, event_id: int, is_new: bool, host: str, iface: str, consec: int diff --git a/static/app.js b/static/app.js index 8b61380..3c544a4 100644 --- a/static/app.js +++ b/static/app.js @@ -135,8 +135,10 @@ function updateEventsTable(events) { const supType = e.event_type === 'unifi_device_offline' ? 'unifi_device' : e.event_type === 'interface_down' ? 'interface' : 'host'; + const ticketBase = (typeof GANDALF_CONFIG !== 'undefined' && GANDALF_CONFIG.ticket_web_url) + ? GANDALF_CONFIG.ticket_web_url : 'http://t.lotusguild.org/ticket/'; const ticket = e.ticket_id - ? `#${e.ticket_id}` : '–'; return ` diff --git a/templates/base.html b/templates/base.html index 0b6bf43..7397bdd 100644 --- a/templates/base.html +++ b/templates/base.html @@ -41,6 +41,11 @@ {% block content %}{% endblock %} + {% block scripts %}{% endblock %} diff --git a/templates/index.html b/templates/index.html index 93cb6e2..498d3ba 100644 --- a/templates/index.html +++ b/templates/index.html @@ -219,7 +219,7 @@ {{ e.consecutive_failures }} {% if e.ticket_id %} - #{{ e.ticket_id }} {% else %}–{% endif %} diff --git a/templates/inspector.html b/templates/inspector.html index af3221a..f1aee6c 100644 --- a/templates/inspector.html +++ b/templates/inspector.html @@ -451,7 +451,11 @@ function pollDiagnostic(jobId, statusEl, resultsEl) { renderDiagnosticResults(resp.result, resultsEl); } }) - .catch(() => {}); + .catch(() => { + clearInterval(_diagPollTimer); + _diagPollTimer = null; + statusEl.textContent = 'Error: lost connection while collecting diagnostics.'; + }); }, 2000); }