Skip to main content

Module writer

Module writer 

Source
Expand description

Bounded, non-blocking background writer for observability persistence (Task 11, spec §6.5).

One cloneable TelemetryWriter handle serves BOTH record kinds:

  • legacy per-request TelemetryRecords → the existing ~/.cache/synaps/api-log.jsonl (format unchanged: one raw JSON object per line, exactly what the old synchronous write_record produced);
  • metadata-only RequestTraces (Tasks 7–10) → a private trace log at ~/.cache/synaps/request-trace.jsonl. Each line is the unwrapped synaps-request-trace/1 object, so any schema-aware reader can parse lines directly.

Design contract:

  • Never blocks the request path. Enqueue is a try_send on a bounded queue; overflow increments a dropped counter (never waits). No awaits, no hidden runtime dependency — the worker is a dedicated OS thread, so sync contexts can enqueue too.
  • Single-owner writes. Only the worker thread touches the files, so size-capped rotation is concurrency-safe by construction.
  • Private files. All paths use the Phase 1 private_fs helpers: parent 0700, file 0600, O_NOFOLLOW (a planted symlink is refused, never followed).
  • Observable, quiet failure. Atomic counters for enqueued/written/dropped/serialization/I-O failures; at most one warning per persistent failure class (queue overflow, serialization, open/write, rotate). Warnings carry a class label only — never record content or paths. The open/write latch re-arms after a successful write so a new persistent failure warns again.
  • Bounded shutdown. TelemetryWriter::shutdown stops intake, drains until the deadline, and returns typed stats. Dropping the last handle simply disconnects the queue: the worker drains what is buffered and exits detached — Drop can never hang.

Production wiring rule (documented until Task 12 adds explicit trace config/UI): telemetry basic/full enables BOTH legacy telemetry persistence and metadata-only trace persistence through this writer; off disables both. The trace schema is structurally metadata-only, so this can never silently persist raw content.

Structs§

TelemetryWriter
Cloneable handle to the bounded background writer.
WriteGate
A gate the writer’s worker waits on before each job (WriterOptions::write_gate). Starts closed; open releases the worker for good.
WriterOptions
Writer configuration. None paths resolve to the installation defaults.
WriterStats
Snapshot of the writer’s atomic counters.
WriterTraceSink
Production TraceSink: enqueues each record onto the shared writer.

Enums§

ShutdownOutcome
Typed result of a bounded shutdown flush.

Constants§

DEFAULT_MAX_FILE_BYTES
Default per-file size cap before rotation (matches the legacy writer).
DEFAULT_QUEUE_CAPACITY
Default bounded queue capacity: deep enough that a briefly slow disk never drops records, small enough to bound memory (records are boxed).
DEFAULT_SHUTDOWN_FLUSH_TIMEOUT
Default budget for the shutdown flush at process-exit epilogues (Task 11): long enough for a healthy disk to drain a full queue, short enough that a hung filesystem can never stall a clean exit.

Functions§

default_telemetry_log_path
Default telemetry log path: ~/.cache/synaps/api-log.jsonl.
default_trace_log_path
Default trace log path: ~/.cache/synaps/request-trace.jsonl.