fix web page issues

This commit is contained in:
Andreas Wrede
2026-04-04 12:43:30 -04:00
parent 941f3ea4b0
commit 73aa89f8f4
3 changed files with 91 additions and 27 deletions
+33 -13
View File
@@ -308,19 +308,29 @@ class Host:
d["dyn"] = str(self.dyn) d["dyn"] = str(self.dyn)
d["num"] = self.num d["num"] = self.num
# Add alert counts # Add alert counts (split by acknowledged status)
warning_count = 0 warning_unacked = 0
critical_count = 0 warning_acked = 0
critical_unacked = 0
critical_acked = 0
for metric_path, alert_state in self.alert_states.items(): for metric_path, alert_state in self.alert_states.items():
# Import AlertLevel here to avoid circular imports # Import AlertLevel here to avoid circular imports
from .threshold import AlertLevel from .threshold import AlertLevel
if alert_state.level == AlertLevel.WARNING: if alert_state.level == AlertLevel.WARNING:
warning_count += 1 if alert_state.acknowledged:
warning_acked += 1
else:
warning_unacked += 1
elif alert_state.level == AlertLevel.CRITICAL: elif alert_state.level == AlertLevel.CRITICAL:
critical_count += 1 if alert_state.acknowledged:
critical_acked += 1
else:
critical_unacked += 1
d["alert_warning_count"] = warning_count d["alert_warning_unacked"] = warning_unacked
d["alert_critical_count"] = critical_count d["alert_warning_acked"] = warning_acked
d["alert_critical_unacked"] = critical_unacked
d["alert_critical_acked"] = critical_acked
for c in ["IPv4", "IPv6"]: for c in ["IPv4", "IPv6"]:
if c in self.connections: if c in self.connections:
@@ -380,18 +390,28 @@ class Host:
ddict[d] = self.__dict__[d] ddict[d] = self.__dict__[d]
# Add alert counts (computed from alert_states) # Add alert counts (computed from alert_states)
warning_count = 0 warning_unacked = 0
critical_count = 0 warning_acked = 0
critical_unacked = 0
critical_acked = 0
if hasattr(self, 'alert_states'): if hasattr(self, 'alert_states'):
from .threshold import AlertLevel from .threshold import AlertLevel
for metric_path, alert_state in self.alert_states.items(): for metric_path, alert_state in self.alert_states.items():
if alert_state.level == AlertLevel.WARNING: if alert_state.level == AlertLevel.WARNING:
warning_count += 1 if alert_state.acknowledged:
warning_acked += 1
else:
warning_unacked += 1
elif alert_state.level == AlertLevel.CRITICAL: elif alert_state.level == AlertLevel.CRITICAL:
critical_count += 1 if alert_state.acknowledged:
critical_acked += 1
else:
critical_unacked += 1
ddict["alert_warning_count"] = warning_count ddict["alert_warning_unacked"] = warning_unacked
ddict["alert_critical_count"] = critical_count ddict["alert_warning_acked"] = warning_acked
ddict["alert_critical_unacked"] = critical_unacked
ddict["alert_critical_acked"] = critical_acked
return ddict return ddict
+48 -12
View File
@@ -276,11 +276,23 @@
c_name.innerHTML = data.name; c_name.innerHTML = data.name;
} }
// Set alert counts // Set alert counts in "x/y" format (unacked/acked)
var warningCount = data.alert_warning_count || 0; var warningUnacked = data.alert_warning_unacked || 0;
var criticalCount = data.alert_critical_count || 0; var warningAcked = data.alert_warning_acked || 0;
c_warning.innerHTML = warningCount > 0 ? warningCount : ""; var criticalUnacked = data.alert_critical_unacked || 0;
c_critical.innerHTML = criticalCount > 0 ? criticalCount : ""; var criticalAcked = data.alert_critical_acked || 0;
if (warningUnacked > 0 || warningAcked > 0) {
c_warning.innerHTML = warningAcked > 0 ? warningUnacked + "/" + warningAcked : warningUnacked;
} else {
c_warning.innerHTML = "";
}
if (criticalUnacked > 0 || criticalAcked > 0) {
c_critical.innerHTML = criticalAcked > 0 ? criticalUnacked + "/" + criticalAcked : criticalUnacked;
} else {
c_critical.innerHTML = "";
}
c_ipv4addr.innerHTML = data.connections[0].addr; c_ipv4addr.innerHTML = data.connections[0].addr;
c_ipv4state.innerHTML = data.connections[0].state; c_ipv4state.innerHTML = data.connections[0].state;
@@ -305,11 +317,23 @@
setup(); setup();
} }
// Update warning and critical counts // Update warning and critical counts in "x/y" format (unacked/acked)
var warningCount = data.alert_warning_count || 0; var warningUnacked = data.alert_warning_unacked || 0;
var criticalCount = data.alert_critical_count || 0; var warningAcked = data.alert_warning_acked || 0;
name_idx[data.name].cells[1].innerHTML = warningCount > 0 ? warningCount : ""; var criticalUnacked = data.alert_critical_unacked || 0;
name_idx[data.name].cells[2].innerHTML = criticalCount > 0 ? criticalCount : ""; var criticalAcked = data.alert_critical_acked || 0;
if (warningUnacked > 0 || warningAcked > 0) {
name_idx[data.name].cells[1].innerHTML = warningAcked > 0 ? warningUnacked + "/" + warningAcked : warningUnacked;
} else {
name_idx[data.name].cells[1].innerHTML = "";
}
if (criticalUnacked > 0 || criticalAcked > 0) {
name_idx[data.name].cells[2].innerHTML = criticalAcked > 0 ? criticalUnacked + "/" + criticalAcked : criticalUnacked;
} else {
name_idx[data.name].cells[2].innerHTML = "";
}
for (var i = 0; i < data.connections.length; i++) { for (var i = 0; i < data.connections.length; i++) {
// Offset by 2 for the warning/critical count columns // Offset by 2 for the warning/critical count columns
@@ -428,8 +452,20 @@
{% for host in hosts %} {% for host in hosts %}
<tr> <tr>
<td>{{ host.name }}</td> <td>{{ host.name }}</td>
<td style="text-align: center; color: #ff9800; font-weight: bold;">{{ host.alert_warning_count if host.alert_warning_count > 0 else '' }}</td> <td style="text-align: center; color: #ff9800; font-weight: bold;">
<td style="text-align: center; color: #f44336; font-weight: bold;">{{ host.alert_critical_count if host.alert_critical_count > 0 else '' }}</td> {%- set warning_unacked = host.alert_warning_unacked -%}
{%- set warning_acked = host.alert_warning_acked -%}
{%- if warning_unacked > 0 or warning_acked > 0 -%}
{{ warning_unacked }}{% if warning_acked > 0 %}/{{ warning_acked }}{% endif %}
{%- endif -%}
</td>
<td style="text-align: center; color: #f44336; font-weight: bold;">
{%- set critical_unacked = host.alert_critical_unacked -%}
{%- set critical_acked = host.alert_critical_acked -%}
{%- if critical_unacked > 0 or critical_acked > 0 -%}
{{ critical_unacked }}{% if critical_acked > 0 %}/{{ critical_acked }}{% endif %}
{%- endif -%}
</td>
{% for conn in host.connections %} {% for conn in host.connections %}
<td>{{ conn.addr if conn.addr else '' }}</td> <td>{{ conn.addr if conn.addr else '' }}</td>
<td>{{ conn.state if conn.state else '' }}</td> <td>{{ conn.state if conn.state else '' }}</td>
+10 -2
View File
@@ -114,11 +114,19 @@ class AlertState:
def to_dict(self) -> dict: def to_dict(self) -> dict:
"""Convert alert state to dictionary for serialization.""" """Convert alert state to dictionary for serialization."""
import math
# Helper to sanitize numeric values for JSON (handle inf/nan)
def sanitize_value(val):
if isinstance(val, float) and (math.isinf(val) or math.isnan(val)):
return None
return val
result = { result = {
"metric_path": self.metric_path, "metric_path": self.metric_path,
"level": self.level.name, "level": self.level.name,
"since": self.since, "since": self.since,
"last_value": self.last_value, "last_value": sanitize_value(self.last_value),
"last_check": self.last_check, "last_check": self.last_check,
"notification_count": self.notification_count, "notification_count": self.notification_count,
"acknowledged": self.acknowledged, "acknowledged": self.acknowledged,
@@ -130,7 +138,7 @@ class AlertState:
# Include threshold info if available # Include threshold info if available
if self.threshold_value is not None: if self.threshold_value is not None:
result["threshold_value"] = self.threshold_value result["threshold_value"] = sanitize_value(self.threshold_value)
if self.operator is not None: if self.operator is not None:
result["operator"] = self.operator result["operator"] = self.operator
if self.formatted_message is not None: if self.formatted_message is not None: