A stored log, timeline_entries, with one row per thing that happened. Each source writes its row in the same transaction as its own record, so the history outlives the 30/90/365-day retention of the tables it points to: - alert events (core/alerts._add_event): fired, resolved, acknowledged, went silent, readings back; - finished Ansible runs (executor, and the startup sweep of interrupted runs): changed something, changed nothing, failed, dry run; - audit rows (core/audit.log_audit): Steward's settings, users and access, sign-ins, backups. Actions another writer records are left to it. Entries carry a kind (fixed) and an area (Service, Host OS, Hardware, Storage, Network, Security, Monitoring). Settings → Timeline edits the areas and each type's area and visibility; both are applied when the timeline is read, so a change re-sorts past entries and a hidden type comes back when shown. Kept forever unless a retention is set. The first start fills the timeline from the last 90 days of records once, skipping any already covered. A host rename carries its entries. UI: Timeline in the sidebar (filter by host, area, kind; scrolls on), a History card on each host page. MCP: get_timeline. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
26 lines
1022 B
HTML
26 lines
1022 B
HTML
{# A host's newest timeline entries, loaded into its page: what happened to it
|
|
lately, with the whole of it a click away. #}
|
|
{% from "_macros.html" import empty_state %}
|
|
{% from "timeline/_entry.html" import entry_what %}
|
|
<section class="card" aria-labelledby="host-history">
|
|
<div style="display:flex;align-items:baseline;justify-content:space-between;gap:1rem;">
|
|
<h3 id="host-history" class="section-title">History</h3>
|
|
<a class="field-hint" href="/timeline/?host={{ host.name|urlencode }}">All of {{ host.name }}'s history</a>
|
|
</div>
|
|
{% if items %}
|
|
<table class="table">
|
|
<tbody>
|
|
{% for item in items %}
|
|
<tr>
|
|
<td class="nowrap" style="width:1%;">{{ item.entry.at|when }}</td>
|
|
<td>{{ entry_what(item) }}</td>
|
|
<td class="nowrap" style="width:1%;">{{ item.entry.actor }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% else %}
|
|
{{ empty_state("Nothing has happened to " ~ host.name ~ " that the timeline records yet.") }}
|
|
{% endif %}
|
|
</section>
|