first commit
This commit is contained in:
67
docs/api-stack/api/api-audit-file/src/retention/retention.md
Normal file
67
docs/api-stack/api/api-audit-file/src/retention/retention.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# `retention`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
Enforces the `maxFiles` retention dimension of the rotation policy by
|
||||
deleting the oldest rotated files until at most `maxFiles` remain.
|
||||
Retention runs immediately after each rotation succeeds so the disk
|
||||
footprint is bounded across long-running deployments — an audit
|
||||
directory left to grow unchecked is the most common operator pain
|
||||
point with file-based sinks, and this module's existence is exactly
|
||||
the answer to it.
|
||||
|
||||
The increment on `api.audit.rotation_evicted_total{sink="file"}` makes
|
||||
eviction observable. Operators alert on an unexpectedly high rate so a
|
||||
runaway rotation cycle (e.g. clock skew, misconfigured `maxAgeMs`) is
|
||||
visible before the retention sweep drops historical data.
|
||||
|
||||
## Features
|
||||
|
||||
- `enforceRetention(fs, basePath, maxFiles, instruments)` — deletes
|
||||
the oldest rotated files until at most `maxFiles` remain. Idempotent:
|
||||
re-running with no surplus is a no-op.
|
||||
- Counter increment per deletion with the canonical `sink="file"`
|
||||
attribute set.
|
||||
- Surfaces `AUDIT_FILE.RETENTION_FAILED` on a delete failure with the
|
||||
offending path in `context.path` and the underlying `cause`.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { enforceRetention } from "@suaveplan/api-audit-file/retention";
|
||||
|
||||
await enforceRetention(fs, "/var/log/audit.log", 30, instruments);
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
Call from a custom rotation cadence — e.g. an external cron that wants
|
||||
to prune without rotating:
|
||||
|
||||
```ts
|
||||
import { enforceRetention } from "@suaveplan/api-audit-file/retention";
|
||||
|
||||
// Cron job: every hour, prune to a smaller retention than the sink's
|
||||
// default to claw back disk during high-traffic windows.
|
||||
setInterval(async () => {
|
||||
await enforceRetention(fs, basePath, 10, instruments);
|
||||
}, 60 * 60 * 1000);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `enforceRetention(fs: FsAdapter, basePath: string, maxFiles: number, instruments: AuditFileInstruments): Promise<void>`
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
`listRotatedFiles` returns paths sorted oldest-first by the embedded
|
||||
ISO timestamp; we slice off the first `(count - maxFiles)` entries and
|
||||
unlink them. Sorting is lexicographic on the ISO string, which is also
|
||||
chronological for the `YYYY-MM-DDTHH-MM-SS.sssZ` shape — no extra
|
||||
parsing required. If `unlink` fails midway, the previously-evicted
|
||||
deletions are not undone; the throw surfaces the failure and the next
|
||||
rotation re-attempts retention against whatever survived.
|
||||
Reference in New Issue
Block a user