fix(diagnostics): bound formatting and release ingress before callbacks

Bound UTF-8 formatting and release diagnostic ingress before invoking
callbacks. Check error-ID collisions at Rust/C++ release final link.

Validation: diagnostic tests, strict Clippy, Miri and final-link cases.
This commit is contained in:
Onur Özkan committed 2026-11-07 18:12:11 +03:00
1 parent 3226ef97fe
commit 84807dde4e
12 files changed
+547 -48

No files matched your search

+16 -12
View File
@@ -1,6 +1,6 @@
# Logs
Kaptan code uses the familiar logging macros on both host and flight targets:
Logging macros work on host and flight targets:
```rust,ignore
kaptan_log::debug!("estimator waiting for IMU");
@@ -11,16 +11,22 @@ kaptan_log::trace!("prediction step complete");
```
All five macros emit `LOG`; their level never selects a different wire
message. When a reportable firmware error escapes a reviewed
message. When a reportable firmware error escapes a
`#[kaptan_err_reportable::propagate]` function, it makes one bounded admission attempt
to the separate `ERROR` ingress.
`kaptan-log` formats each event once into a fixed bounded buffer and never
sends MAVLink, allocates, blocks, changes flight state, or touches DMA. The
composition fans the event into each enabled sink; the sole MAVLink worker
drains its bounded sink queue. Ordinary log text uses one 160-byte bounded
record. Reportable-error records contain the explicit ID and a static reference
to the reporting point until the MAVLink adapter copies its
`kaptan-log` formats each event once into fixed 160-byte UTF-8 storage. Its core
storage and admission paths use no allocation or blocking, and do not send
MAVLink, change flight state or touch DMA. Formatting invokes caller-supplied
`Display` implementations, which may allocate, block, ignore `fmt::Error` or do
unbounded work. Overflow stops formatters that propagate the error and latches
truncation even if a formatter ignores it. Bounded storage is not a universal
worst-case execution-time guarantee. Producers must choose formatters suitable
for their execution context.
The composition fans the event into each enabled sink. The MAVLink worker drains
its bounded sink queue. Reportable-error records contain the explicit ID and a
static reference to the reporting point until the MAVLink adapter copies its
`file:line` into the 96-byte `raised_at` field.
Logs and reportable errors use independent fixed atomic
ingresses; interrupt and worker producers make one nonblocking admission
@@ -47,8 +53,6 @@ or the complete field when no zero is present.
(2), Info (3), Warn (4), or Error (5). Off (0) is a filter-only sentinel and
is never emitted as a `LOG` event. `LOG.flags` currently owns only the
Truncated bit (1).
The `ERROR` message kind already means a reportable firmware error, so it has
no redundant level or flags field.
`error_id` is the stable nonzero catalog number explicitly assigned to the
Rust error variant. Renaming or reordering a variant does not change it.
@@ -73,8 +77,8 @@ runtime log levels. F722 uses the validated filter recovered at boot, falling
back to its board factory when the journal is empty or invalid.
Events retain the compact typed `Level` and sink configuration retains the
compact typed `LevelFilter`. Generic schema discovery exposes the filter's
named choices to the configurator, so the UI carries no hardcoded field list.
compact typed `LevelFilter`. Schema metadata supplies the filter choices to the
configurator.
Only the MAVLink adapter converts the five event levels to the typed Kaptan
wire enum.