#5066 "Alert history page". /alerts/history lists every alert transition in a range (1h–30d, the shared range picker), newest first, all rules or one (?rule=). Each row: from → to, the value against the rule's condition ("no data" for a silent one), email and webhook sent or failed with the error, "muted · <window>" (and "notified when the window ended") taken out of the event note, other notes, and a link to the Ansible run an action started. Range and rule changes swap only the rows (HTMX). Viewer role. The Alerts page links each rule's history and the whole history. The query moves to alert_svc.history, which MCP get_alert_history now uses too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
76 lines
3.4 KiB
HTML
76 lines
3.4 KiB
HTML
{# alerts/_history_rows.html — the history table; swapped in on a range or rule change #}
|
|
{% set state_badge = {"firing": "badge-red", "pending": "badge-yellow", "acknowledged": "badge-gold",
|
|
"resolved": "badge-green", "inactive": "badge-dim"} %}
|
|
{% if events %}
|
|
<div class="card-flush" style="overflow-x:auto;">
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>When (UTC)</th>
|
|
<th>Rule</th>
|
|
<th>Change</th>
|
|
<th>Value</th>
|
|
<th>Notified</th>
|
|
<th>Action</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for ev in events %}
|
|
<tr>
|
|
<td style="font-family:ui-monospace,monospace;font-size:0.82rem;white-space:nowrap;">
|
|
{{ ev.at.strftime("%Y-%m-%d %H:%M:%S") }}
|
|
</td>
|
|
<td>
|
|
<a href="/alerts/history?rule={{ ev.rule.id }}&range={{ current_range }}">{{ ev.rule.name }}</a>
|
|
<div style="font-size:0.78rem;color:var(--text-dim);">{{ ev.rule.source_module }}/{{ ev.rule.resource_name }}</div>
|
|
</td>
|
|
<td style="white-space:nowrap;">
|
|
<span class="badge {{ state_badge.get(ev.from_state, 'badge-dim') }}">{{ ev.from_state }}</span>
|
|
<span style="color:var(--text-dim);">→</span>
|
|
<span class="badge {{ state_badge.get(ev.to_state, 'badge-dim') }}">{{ ev.to_state }}</span>
|
|
{% for n in ev.notes %}
|
|
<div style="font-size:0.78rem;color:var(--text-muted);margin-top:0.25rem;white-space:normal;">{{ n }}</div>
|
|
{% endfor %}
|
|
</td>
|
|
<td style="font-family:ui-monospace,monospace;font-size:0.85rem;white-space:nowrap;">
|
|
{{ ev.rule.metric_name }} = {{ ev.value }}
|
|
<div style="font-size:0.75rem;color:var(--text-dim);">rule: {{ ev.condition }}</div>
|
|
</td>
|
|
<td style="font-size:0.82rem;">
|
|
{% if ev.muted_by %}
|
|
<span class="badge badge-yellow" title="A maintenance window muted this notification">muted · {{ ev.muted_by }}</span>
|
|
{% if ev.released %}<div style="color:var(--text-muted);margin-top:0.25rem;">notified when the window ended</div>{% endif %}
|
|
{% endif %}
|
|
{% for label, sent, error in ev.deliveries %}
|
|
<div style="margin-top:0.15rem;">
|
|
{% if sent %}
|
|
<span class="badge badge-green">{{ label }} sent</span>
|
|
{% else %}
|
|
<span class="badge badge-red">{{ label }} failed</span>
|
|
{% if error %}<div style="color:var(--text-muted);font-size:0.78rem;margin-top:0.15rem;max-width:28rem;word-break:break-word;">{{ error }}</div>{% endif %}
|
|
{% endif %}
|
|
</div>
|
|
{% endfor %}
|
|
{% if not ev.muted_by and not ev.deliveries %}<span style="color:var(--text-dim);" title="No notification was sent for this change">—</span>{% endif %}
|
|
</td>
|
|
<td style="font-size:0.82rem;">
|
|
{% if ev.ansible_run_id %}
|
|
<a href="/ansible/runs/{{ ev.ansible_run_id }}">Ansible run</a>
|
|
{% else %}<span style="color:var(--text-dim);">—</span>{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% if truncated %}
|
|
<p style="color:var(--text-muted);font-size:0.82rem;margin-top:0.75rem;">
|
|
Showing the newest {{ limit }}. Pick a shorter range or one rule to see the rest.
|
|
</p>
|
|
{% endif %}
|
|
{% else %}
|
|
<p style="color:var(--text-muted);">
|
|
No alert changed state in the last {{ current_range }}{% if chosen %} for {{ chosen.name }}{% endif %}.
|
|
</p>
|
|
{% endif %}
|