Expand description
Records raised before any sink was installed.
§The problem this exists for
crate::init publishes the sink list. A record raised before that call
has nowhere to go, and for most of this crate’s life it was constructed,
dispatched and DROPPED — silently, and invisibly to its author, who cannot
know what the board did before reaching their code.
Issue 0708 answered by requiring every board boot funnel to call
init_default(), gated on funnels spelled pub fn run*. That is a SEARCH
for boot paths and it kept losing: NuttX’s funnel is pub extern "C" fn nsh_main, and three board crates did not link nros-log in the
configuration holding the funnel at all.
Issue 0710 answered by having dispatch install the platform sink itself.
That removed the search — but it put nros_platform_log_write on a path
EVERY binary executes, which turned a pluggable delivery into a LINK-TIME
requirement. Seven test targets in nros-rmw-cffi and most of nros-tests
stopped linking under check-workspace-features, and no Cargo feature can
fix that: nros-platform-cffi and nros-rmw-bridge enable
nros-node/rmw-cffi unconditionally, so feature unification turns any
forwarded gate back ON for every member of a workspace build. A feature is a
property of the BUILD; what the question needs is a property of the BINARY.
§A funnel is not always a board method — issues 1048 and 1123
The search above kept losing for one more reason, and it is worth naming
because it defeats the obvious grep: not every boot funnel lives in a
board crate. nros::main! emits a different entry shape per framework,
and two of them reach no BoardEntry method at all —
Framework::Zephyr(and its single-node siblingnros::zephyr_component_main!) emitsrust_maindirectly, because Zephyr owns the Cmainand a Rust staticlib cannot take it over. That is whynros-board-zephyrhas onlyrun_tiersto install from, and why a single-tier pure-Rust Zephyr image published no sink list for two phases (issue 1123) while itslog::info!s worked fine.- a
[[bridge]]system replaces the register/spin body withnros_bridge::run_from_config_str, so it reaches no board either.
Both now call nros_platform::log::init_default() — reached through
nros-platform (which re-exports nros_platform_cffi::log) because that is
the crate a generated Entry and the Zephyr example leaves already declare;
giving each leaf a nros-platform-cffi dep of its own is the link-time
requirement 0710 rejected.
So the enumeration is board crates PLUS the framework arms of
nros-macros’ main_macro.rs PLUS nros’ entry macros. Sweep it with:
grep -rn 'Framework::[A-Za-z]* => ' packages/core/nros-macros/src/main_macro.rs
grep -rn 'init_default()' packages/boards packages/core/nros-macros packages/api/nros§What this does instead
Hold the records. A record raised with no sinks installed is copied into a
bounded static ring here; crate::init drains it into whatever sinks the
board actually chose. Nothing is dropped, no board can forget, and this
crate touches no platform symbol to do it — the facade stays a facade.
It is also STRICTLY better than installing a default sink was: the early records land in the sink the board picked, rather than in whichever one dispatch guessed before the board had spoken.
§Cost, and how to decline it
EARLY_DEPTH * (format buffer + name + header) of static RAM, all of it in
.bss. The depth is the NROS_LOG_EARLY_RECORDS knob (issue 1037; builtin
4, resolved by build.rs on the RFC-0049 ladder — it replaced the
early-records-<N> features), because a 64 KB MCU and a Linux host do not
want the same number. 0 declines the buffer entirely and restores the
pre-0708 behaviour of dropping, with the count below still kept so the loss
is at least reportable.
Overflow is counted, never silently absorbed: overflowed returns how
many records did not fit, and init reports it through the freshly
installed sinks.
Functions§
- early_
depth - Records held before
init. See the module docs for the trade. - overflowed
- How many early records did not fit and were lost.