Log Writer v1
September 10, 2026 ยท View on GitHub
Status: implemented additive source profile; HOSTED GREEN under the v0.4.0 release baseline.
Audience: standard-library contributors, compiler maintainers, and backend implementers.
std.log provides a bounded structured JSON-lines writer for one caller-owned
event. It composes the existing std.io.Writer, JSON quoting, and decimal
formatting helpers without ambient effects or hidden allocation.
Event and output
The public source declarations are:
std.log.Event {
level: u8,
sequence: usize,
name: Bytes,
message: Bytes,
}
std.log.append_event(event: own Event, output: own std.io.Writer)
-> std.io.Writer
Levels are encoded as trace (0), debug (1), info (2), warn (3), and
error (4); level 5 is fatal. The writer emits one complete JSON object and
a trailing line feed:
{"level":"info","sequence":7,"event":"a\"","message":"\n"}
name and message are quoted with the existing JSON writer policy. The
sequence is decimal ASCII. level_len, level_byte, fixed_len, and
fixed_byte are source-visible checked helpers for the fixed punctuation and
level words; event_json_len computes the exact complete output length.
Validation and ownership
Before the first output write, append_event validates the level, validates
the UTF-8 content of name and message through std.data.json.utf8, and
checks the Writer position and complete remaining capacity. A malformed event,
invalid level, or short/forged output Writer is rejected without partial JSON,
cursor advancement, or published replacement Writer. The event and Writer are
consumed together at the ordinary owned-call boundary; successful output
advances by exactly the emitted bytes and preserves the unwritten suffix.
The package uses the private useful-data.v2 profile and exactly the bundled
std.data.json.utf8, std.data.json.write, and std.io dependencies. It no
longer depends on std.format; count_into and usize_len come directly from
the JSON writer package. It has no public exports, hidden allocation,
filesystem/process/network effect, or other ambient authority. This is a
bounded JSON-lines event writer, not a general logging framework, hosted log
service or production logging facility.
Level filtering
Filtering is the additive half of the same profile, and it is explicit rather than ambient:
std.log.level_enabled(level: u8, threshold: u8) -> bool
std.log.event_admitted(event: borrow Event, threshold: u8,
output: borrow Writer) -> bool
std.log.discard_event(event: own Event, output: own Writer)
-> std.io.Writer
std.log.append_event_if(event: own Event, threshold: u8,
output: own Writer) -> std.io.Writer
Levels run 0 (trace) to 5 (fatal), and an event is enabled when its level
is at or above the threshold, so a threshold of 0 admits everything and 5
admits only fatal events. event_admitted is the borrowed observer a caller
checks before committing: it is true only when the event both passes the
threshold and fits the writer's live capacity.
append_event_if writes the event exactly as append_event does when it
passes, and otherwise consumes the event and returns the caller's Writer
untouched, with no byte written and the cursor unchanged. Capacity is therefore
required only for an event that is actually written: a filtered event needs no
room at all, which is what makes a small buffer plus a high threshold a valid
composition rather than a contract failure. discard_event is that drop path
named on its own, for a caller that decides policy itself; both transitions
consume the event, so a dropped event releases its name and message bytes
through ordinary lexical cleanup rather than leaking them.
A filtered event is dropped, not buffered: the profile adds no queue, no sink, no timestamp source, no redaction, and no concurrency. Nothing here observes a clock or a process, and no filtering decision is taken outside the caller's own call.
Focused verification
The canonical package checks a complete 59-byte escaped line and all five
unwritten zero suffix bytes. Fifteen expanded cases are kept in
tests/project/standard_library/log_cases.spx; each case preserves the exact
local call closure and required type imports. They include all six levels,
valid two-, three-, and four-byte UTF-8, exact capacity, prefix/suffix
preservation, and a fully checked 300-byte message. The unchanged canonical
package also runs. ASCII scanning uses the existing byte-range predicate
directly instead of probing each byte numerically; multibyte validation and
the interpreter fuel limit are unchanged. An explicit inventory requires
every case and direct executed coverage of every public source function.
The maintained focused selectors are:
logging::log_writer_executes_on_all_three_backends
logging::log_writer_preflight_rejects_invalid_events
logging::utf8_ascii_scan_preserves_package_conformance
The original local witness exercised the shipped package and all fifteen cases
on the interpreter, C11 at -O0 and -O2, and four repeated Core Wasm
invocations. The Wasm harness enforces each case's exact live Bytes bound:
zero for pure helpers, one or two for individual operations, and three for a
complete event and Writer. Every invocation returns with no live Bytes.
Nine malformed UTF-8, invalid level, short-capacity, and forged-cursor cases
passed twice through the bundled consumer with the exact requires-false
status. The UTF-8 package's existing conformance also passed on all three
backends, together with catalog, metadata, formatting, document-link and
module-size checks.
The released implementation is hosted green; the earlier local counts remain
historical observations. Broader Everyday standard-library completion remains
Partial: general logging facilities, sinks, filtering, timestamps and
concurrency are outside this source-writer slice.