4.1 The Log Writer

One thread reads datagrams from the log socket and writes log records to the log store. It is independent of the event drain and writer threads, so log ingestion never contends with event ingestion.

The wire contract — socket type, datagram ceiling, record format, and exactly which malformations cost what — is PSPU §3.6 to §3.8. What follows is what eventd does with a record once it has one.

4.1.1 One thread does both jobs #

The log thread performs both the socket reads and the SQLite writes.

The consequence is direct: during a batch commit the socket is not being drained, and datagrams arriving in that window occupy the receive queue until it fills, after which the kernel discards them. The queue — SO_RCVBUF — is sized at four times the datagram ceiling, and it is the whole cushion.

Splitting into a reader and a writer with a bounded handoff — the shape the event path uses (§2.3) — would decouple them. It is not done, and the reasoning is that log loss is tolerable by design (PSPU §3.4), log volume is normally well below event volume, and the single-thread model avoids a handoff channel and its backpressure semantics entirely.

Where log throughput does become the constraint, sharding the log store the way the event store is sharded is the larger lever; splitting the thread only moves the stall.

4.1.2 Batching #

The writer batches on the same adaptive principle as the event writer (§2.4), with the socket receive queue as its input. A transaction opens when the first valid record is available and commits when any of these holds:

  • no further datagram is immediately available in the receive queue
  • the batch holds LogMaxBatchSize records
  • LogMaxBatchLatencyMs has elapsed since the first record entered it

If a datagram yields more valid records than fit in the remaining space, the writer commits, then continues with the same datagram in a new transaction. A transaction never exceeds the size cap and never stays open past the latency cap — a batched datagram cannot smuggle a larger transaction past either.

The defaults (§A) are 5000 records and 500 milliseconds. The latency is five times the event writer's, because log loss on power failure is acceptable where event loss is not, and larger, less frequent transactions are more efficient at the moderate volumes logs normally run at.

4.1.3 Durability #

The log store runs in WAL mode with synchronous=NORMAL, not FULL.

NORMAL syncs at checkpoint time rather than at every commit. It is durable against process crashes — the write-ahead log survives — but not against power loss, where commits since the last checkpoint may be gone.

This is a deliberate divergence from the event store, and it is the single clearest expression of the hierarchy the whole daemon is organised around: events are sacred, logs are not. Paying an fsync per transaction to protect data whose loss is defined as acceptable would be paying for nothing.

4.1.4 Adding to the record #

eventd supplies the boot_id and, where the producer omitted timestamp, its own clock at receipt. Everything else is stored as given — message byte for byte (PSPU §3.8).

Edit this page