Files
kaptan/docs/src/logs.md
T
Onur Özkan f9a61a086f feat(firmware): validate configuration and migrate sensor-driven flight APIs
Validate configuration through its owning schemas and keep board
declarations separate from shared F722 resource ownership. Bound USB
transitions, isolate transport failures and retain restart-only activation.

Migrate navigation and flight consumers with the sensor and schema
contracts. Require explicit installation data and synchronous output
authority; board motor outputs remain inhibited.

Validation: assembled-prefix host tests, strict Clippy, platform/USB tests
and both ARM release builds. Final-source coverage and scoped Miri/Kani
evidence are retained separately from hardware qualification.
2026-11-07 18:12:11 +03:00

4.2 KiB

Logs

Logging macros work on host and flight targets:

kaptan_log::debug!("estimator waiting for IMU");
kaptan_log::info!("configuration loaded");
kaptan_log::warn!("range aid stale");
kaptan_log::error!("sensor transfer failed");
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 #[kaptan_err_reportable::propagate] function, it makes one bounded admission attempt to the separate ERROR ingress.

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 attempt, and only the MAVLink worker encodes or transmits a retained event. Panic and hard-fault paths still do not attempt live telemetry.

Receiver contract

definitions/publish/log.xml and definitions/publish/error.xml define the separate ordinary-log and reportable-error publications:

LOG { level, flags, message_length, message[160] }
ERROR {
  error_id, raised_at[96]
}

A GCS decoder generated from the same kaptan.xml revision must validate message_length <= 160 for LOG. ERROR.raised_at is a zero-padded UTF-8 file:line prefix; receivers use bytes before the first zero, or the complete field when no zero is present. LOG.level is the typed severity-ordered Kaptan wire enum Trace (1), Debug (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).

error_id is the stable nonzero catalog number explicitly assigned to the Rust error variant. Renaming or reordering a variant does not change it. raised_at identifies the reporting point where the Err entered diagnostics. Protocol failures remain in their owning response; for example, a rejected KCFG upload returns a FILE_CONTROL failure and readable bounded detail. Delivery is bounded and lossy under link pressure. Heartbeat and sensor telemetry use separate paths. Logs have no publication rate setting and are not periodic streams. The worker offers each retained event to USB and every MAVLink UART, then removes it once at least one transport admits it. Admission does not prove receipt or delivery to every link. If none admits it, the event remains pending. Opening USB does not take diagnostics away from UART.

Filtering

The single restart-only mavlink.logging.level_filter field uses Off (0), Trace (1), Debug (2), Info (3), Warn (4), and Error (5). Info, for example, accepts Info, Warn, and Error log events. Off suppresses LOG on MAVLink without suppressing reportable ERROR events or logs sent to another sink. There is no separate enable flag and no MAVLink-specific set of extra runtime log levels. F722 uses the validated boot-active filter. Empty storage uses factory values. Invalid storage selects the setup fallback, which also uses the factory filter but disables UART roles. Saved changes and factory reset do not alter the active filter until reboot. See configuration recovery.

Events retain the compact typed Level and sink configuration retains the 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.

The log ingress is transport-neutral and unfiltered.