Files
sencho/docs/features/stack-activity.mdx
T
Anso 35bb74425b feat: guide missing external network creation during deploy (#1645)
* feat: guide missing external network creation during deploy

Detect missing external networks before Compose runs, prompt or auto-create safe bridge networks, and keep unsupported declarations blocked with trusted deploy provenance.

* test: align deploy context and settings fixtures with missing-network gate

Update caller spies, EffResource expectations, StacksSection save keys, and git-source spy cleanup so CI matches the new deployStack context and auto-create setting.

* fix: drop unused renderError binding in missing-network resolver

Satisfies no-unused-vars so backend ESLint CI passes; callers already key only on model presence.

* fix: use HTTP-safe clipboard helper in missing-network dialog

navigator.clipboard fails on plain HTTP LAN hosts; route copy actions through copyToClipboard so Docker and Compose copy buttons work on self-hosted instances.

* fix: simplify missing-network dialog actions and copy label

Drop the Compose snippet escape hatch, move secondary actions under More, and rename the terminal copy action to Copy create command so the footer is a clear Cancel / Create decision.
2026-07-17 14:51:00 -04:00

126 lines
8.5 KiB
Plaintext

---
title: Stack Activity
description: Per-stack event log showing deploys, restarts, config changes, and alerts, each attributed to the user or system process that triggered them.
---
The **Activity** tab in the right-hand **Anatomy** panel gives you a timestamped record of everything that happened to the selected stack: deploys, restarts, stops, starts, image updates, drift events, and health gate outcomes. Every entry is attributed to the user or background process that triggered it, so you always have full operational context at a glance. The **files** and **edit** buttons on the same header strip belong to the panel as a whole and stay available regardless of which tab is active.
<Frame>
<img src="/images/stack-activity/activity-tab-populated.png" alt="Activity tab with the ACTIVITY tab selected in the header strip showing ANATOMY, ACTIVITY, DOSSIER, DRIFT, ENVIRONMENT, NETWORKING, DOCTOR, STORAGE tabs. Under a TODAY header, three events appear: 'plex deployed by admin' with a rocket icon 52m ago, 'plex updated by admin' with an up-arrow icon 12h ago, and 'plex update started by admin' with an up-arrow icon 12h ago." />
</Frame>
## What you'll see
Each entry in the activity list contains four pieces of information:
| Field | Description |
|-------|-------------|
| **Icon** | Category of the event (deploy, restart, stop, start, image update, drift, and others) |
| **Message** | What happened, for example `plex deployed`. Sensitive values such as tokens, secrets, basic-auth credentials, and bearer tokens are redacted before storage |
| **Attribution** | `by <username>` for user-initiated actions; `via <Subsystem>` for events triggered by background processes such as Auto-Heal or the Scheduler |
| **Time** | Relative time since the event: `just now`, `5m ago`, `2h ago`, `3d ago` |
## Event categories
Ten categories have a dedicated icon. Any other notification scoped to a stack (deploy failures, scan findings, monitor alerts) also flows into the timeline and renders with a generic activity icon. Automatic creation of missing external networks during deploy writes a history-only activity row (`network_auto_created`) on the stack timeline; it does not appear in the notification bell.
| Category | Example message |
|----------|-----------------|
| Deploy succeeded | `plex deployed` |
| Stack restarted | `dozzle restarted` |
| Stack stopped | `radarr stopped` |
| Stack started | `radarr started` |
| Image update applied | `Auto-update: stack "dozzle" updated with new images` |
| Drift detected | `Drift detected on sonarr: 2 findings` |
| Drift resolved | `Drift resolved on tautulli: 1 finding cleared` |
| Update started | `tautulli update started` |
| Health gate passed | `plex: health gate passed` |
| Health gate failed | `plex: health gate failed` |
## Day grouping
Events are grouped by day under three headers: **Today**, **Yesterday**, and **Earlier**. Within each group, events appear most-recent first. The grouping recomputes every minute so a panel left open past midnight automatically rolls the **Today** bucket into **Yesterday**.
## Live updates
New events stream in over the same WebSocket that powers the notification bell. The list updates without a page refresh while the tab is open. Duplicate events are deduplicated by ID, and the timeline is sorted by `(timestamp, id)` so events emitted within the same millisecond stay in a stable order.
If the WebSocket connection drops, a banner appears at the top of the timeline:
> Live updates offline; reconnecting…
New events are paused until the connection re-establishes. Existing entries remain visible. Once the banner clears, new events resume automatically without any action on your part.
## Pagination
The tab loads the 50 most recent events on open. If a stack has more recorded events, a **Load more** button appears at the bottom of the list. Each click fetches the next 50 older events. The button disappears once the timeline reaches the end of the stored history.
The underlying API endpoint, `GET /api/stacks/{stackName}/activity`, accepts an optional `before` (timestamp) and `beforeId` (row id) pair for cursor-based pagination. Both parameters must be sent together; sending `beforeId` without `before` is rejected.
## Empty state vs unavailable
Two states can make the tab look empty, and they mean different things:
- **No activity recorded yet** appears when the stack genuinely has no recorded events. This is normal for stacks that have not had any lifecycle actions since Sencho began tracking activity.
- **Activity unavailable** appears when the request to fetch events fails (for example, the node became unreachable mid-load). A **Retry** button is shown next to this message.
<Frame>
<img src="/images/stack-activity/activity-tab-empty.png" alt="Activity tab showing a small activity icon and the message 'No activity recorded yet' centered in the panel, with no events listed." />
</Frame>
## Who triggered an event
Sencho attributes every recorded event to the actor that performed it:
- **User-initiated actions** (deploy, restart, stop, start, image update triggered from a button or the API): the actor is the authenticated username, shown as `by <username>`.
- **Background subsystems**: the actor is the subsystem name, shown as `via <Subsystem>`.
| Background subsystem | Displayed as |
|----------------------|--------------|
| Generic system event | `via System` |
| Auto-Heal | `via Auto-Heal` |
| Scheduler | `via Scheduler` |
| Image Update | `via Image Update` |
| Docker event monitor | `via Docker` |
| Blueprint reconciler | `via Blueprint` |
| Host Monitor | `via Monitor` |
| Policy enforcement | `via Policy` |
An Auto-Heal restart and a manual restart produce separate entries in the timeline because their actors differ, even when the event message is otherwise identical.
## Retention
Activity is stored in a per-instance SQLite table. Two limits apply, whichever is reached first:
- **Time-based:** events older than the configured retention window (30 days by default) are removed during the next periodic cleanup.
- **Per-stack cap:** the most recent 500 events per (node, stack) are kept. Older events for that stack are pruned on the next cleanup run.
Events without an associated stack (system-level notifications) are kept up to 1,000 per node before the oldest are removed.
Cleanup runs on the same schedule as container-metrics cleanup, so retention applies even on long-running instances.
## Accessing the Activity tab
1. Click any stack in the left sidebar to open it.
2. Select the **Activity** tab in the Anatomy panel header.
## Troubleshooting
<AccordionGroup>
<Accordion title="The Activity tab shows 'No activity recorded yet'">
This is normal for stacks that have not had any lifecycle actions (deploy, restart, stop, update) since Sencho started tracking activity. The tab populates the first time a lifecycle event is recorded. Events that occurred before Sencho was installed are not backfilled.
</Accordion>
<Accordion title="The Activity tab shows 'Activity unavailable'">
The request to fetch activity failed, usually because the node is unreachable or the backend returned a server error. Click **Retry** to re-fire the request without reloading the page. If the node has been removed or its credentials have changed, go to **Settings → Nodes** to verify the connection.
</Accordion>
<Accordion title="An event I triggered is not appearing in the timeline">
Live events arrive over WebSocket. If the "Live updates offline; reconnecting…" banner is visible, new events are paused until the connection recovers. Scroll down to check whether the event is already present below the visible viewport, or wait for the banner to clear and the event will appear automatically. If the event still does not show up, check the notification bell for error-level alerts that may indicate the action itself did not complete.
</Accordion>
<Accordion title="The same restart shows as both 'by &lt;username&gt;' and 'via Auto-Heal'">
These are two distinct events. The first is a manual restart; the second is Auto-Heal restarting the container after a separate unhealthy-duration breach. Each event is its own entry with its own actor. Two rows here are correct behavior, not a duplicate.
</Accordion>
<Accordion title="Operational events don't appear in the notification bell dropdown">
The notification bell surfaces system alerts and error-level events. User-initiated operational events (start, stop, restart, deploy, update) appear exclusively in the per-stack Activity tab, keeping the global tray focused on conditions that need your attention.
</Accordion>
</AccordionGroup>