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
|
Per-equipment |
- class exlab_wizard.logging.handlers.EquipmentScopedFileHandler(local_root, *, hostname=None)[source]#
Bases:
HandlerPer-equipment
wizard.<hostname>.logwriter.Resolves
<local_root>/<equipment_id>/.exlab-wizard/wizard.<hostname>.logat emit time from the activeequipment_idcontext var. Lazy-opens the file on first emit and caches the file object per equipment for the process lifetime.O_APPENDsemantics on POSIX (and the equivalent share-mode flags on Windows) keep concurrent emits tear-free without explicit locking.Construct with the configured
local_root(apathlib.Path). The handler accepts an optionalhostnamekwarg so tests can pin a deterministic value; production callers leave it asNoneand the handler resolvessocket.gethostname()once on construction.Events without an
equipment_idin context are skipped: they fall through to the central handler downstream (which has no scope requirement).