vibeqc.StructuredLog

class vibeqc.StructuredLog(path=None, *, enabled=True)[source]

Bases: object

One-record-per-line NDJSON writer with line-flushed I/O.

Construct via structured_log() (the context manager) for the common case. Direct construction is supported for tests / advanced callers that want to manage the lifetime themselves — call close() when done.

Parameters:
  • path (Union[str, os.PathLike, None]) – Destination NDJSON file. Truncated on construction so a fresh run doesn’t accumulate alongside last week’s tail. The parent directory is created if missing.

  • enabled (bool) – If False, all emit() calls are no-ops and the file is not opened. Lets callers pass through a StructuredLog unconditionally without wrapping every emit in an if log: guard.

Notes

Each emit() call:

  • stamps timestamp (ISO-8601 with timezone) onto the record,

  • encodes via json.dumps() with allow_nan=False (jq- compatible),

  • writes a single line + \n, then flush() so a tail -f sees records as they land.

A logging failure (disk full, permissions, …) is caught and a one-line warning emitted to stderr; the calculation continues. This matches vibeqc.ProgressLogger and vibeqc.PerfTracker.

__init__(path=None, *, enabled=True)[source]
Parameters:
Return type:

None

Methods

__init__([path, enabled])

close()

Flush + close the underlying file handle.

emit(event, **payload)

Write one record with "event": event plus payload.

Attributes

enabled

n_emitted

Number of records successfully written so far.

path

emit(event, **payload)[source]

Write one record with "event": event plus payload.

payload keys overwrite "event" if a caller passes event=... as a kwarg — last-write-wins, matching dict construction.

Parameters:
Return type:

None

close()[source]

Flush + close the underlying file handle. Safe to call multiple times. After close(), emit() is a no-op.

Return type:

None

property enabled: bool
property path: Path | None
property n_emitted: int

Number of records successfully written so far.