Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Logging

Consistent logging makes debugging tractable across a large kernel codebase.

Use OSTD logging macros exclusively (ostd-log-only)

All OSTD-based crates must use the logging macros provided by the ostd::log module: debug!, info!, notice!, warn!, error!, crit!, alert!, emerg!. Import them via use ostd::prelude::* or use ostd::log::{info, warn, ...}.

Do not use the third-party log crate directly. OSTD provides a bridge that forwards messages from third-party crates (e.g., smoltcp) that use log, but first-party code must use OSTD’s macros.

Custom output functions, println!, and hand-rolled serial print macros are not acceptable in production code. Exception: code that runs before the logging subsystem is initialized may use early-boot output helpers.

// Good
info!("VirtIO block device initialized: {} sectors", num_sectors);

// Bad — using the log crate directly
log::info!("VirtIO block device initialized: {} sectors", num_sectors);

// Bad — using println
println!("VirtIO block device initialized: {} sectors", num_sectors);

Choose appropriate log levels (log-levels)

OSTD provides eight log levels matching the severity levels described in syslog(2):

LevelUse for
emerg!System is unusable; immediately before abort().
alert!Action must be taken immediately.
crit!Critical conditions: unrecoverable resource exhaustion.
error!Serious but recoverable failures: invariant violations, I/O errors.
warn!Recoverable problems: fallback paths taken, deprecated usage detected.
notice!Normal but significant events: CPU online, security feature activated.
info!Routine informational events: subsystem initialization, configuration changes.
debug!Development diagnostics: state transitions, intermediate values, per-packet tracing.

Use error! for failures that the system can recover from. Use crit! or emerg! only for failures immediately before a halt or abort. A log statement that fires on every syscall or every timer tick must use debug!.

Define a log prefix for each crate (log-prefix)

Every OSTD-based crate must define a __log_prefix macro at its crate root (in lib.rs), before any mod declarations. This labels all log messages from the crate:

// Set this crate's log prefix for `ostd::log`.
macro_rules! __log_prefix {
    () => {
        "virtio: "
    };
}

Convention: use the lowercase crate name (without aster_ prefix), followed by : . For example: "virtio: ", "pci: ", "uart: ".

Subsystem modules within a crate can override the prefix by defining their own __log_prefix at the top of mod.rs:

// Set this module's log prefix for `ostd::log`.
macro_rules! __log_prefix {
    () => {
        "net: "
    };
}

Child modules inherit the override automatically.

Do not put #[rustfmt::skip] or any other attribute on __log_prefix definitions — it causes a compiler ambiguity error (E0659).

Do not use manual bracket prefixes like [IOMMU] or [Virtio]:. The __log_prefix mechanism replaces them.