exlab_wizard.logging.handlers#

Equipment-scoped file handler. Backend Spec §16.2.4.

The EquipmentScopedFileHandler resolves its destination at emit time using the active context’s equipment_id. There is one file descriptor open per equipment, cached for the lifetime of the process; concurrent emits from the same hostname use O_APPEND semantics (POSIX) or FILE_APPEND_DATA | FILE_SHARE_WRITE (Windows) so writes don’t tear (§4.5 same-equipment concurrency rule).

fsync is called only on ERROR-level events. INFO/DEBUG emits are flushed but not fsync’d, matching §16.2.4: durability matters for hard failures, throughput matters for routine traffic.

Events without an equipment_id in context are silently skipped here – they reach the central handler via the same queue listener.

Classes

EquipmentScopedFileHandler(local_root, *[, ...])

Per-equipment wizard.<hostname>.log writer.

class exlab_wizard.logging.handlers.EquipmentScopedFileHandler(local_root, *, hostname=None)[source]#

Bases: Handler

Per-equipment wizard.<hostname>.log writer.

Resolves <local_root>/<equipment_id>/.exlab-wizard/wizard.<hostname>.log at emit time from the active equipment_id context var. Lazy-opens the file on first emit and caches the file object per equipment for the process lifetime. O_APPEND semantics on POSIX (and the equivalent share-mode flags on Windows) keep concurrent emits tear-free without explicit locking.

Construct with the configured local_root (a pathlib.Path). The handler accepts an optional hostname kwarg so tests can pin a deterministic value; production callers leave it as None and the handler resolves socket.gethostname() once on construction.

Events without an equipment_id in context are skipped: they fall through to the central handler downstream (which has no scope requirement).

Parameters:
close()[source]#

Close every cached file descriptor.

Called on listener teardown. Idempotent: a second call is a no-op because the cache is cleared on first close.

Return type:

None

emit(record)[source]#

Write record to the active equipment’s log file.

Parameters:

record (LogRecord)

Return type:

None