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):
| Level | Use 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.