The main limitation of this simple implementation is that all events/spans are deliberately sinkholed by the MockSubscriber, as a most off-the-shelf subscribers depend on the standard library. In the future, it would be nice to get those to work properly, but this simple approach should work fine for now.
S2RR5DIKAB5T5J5LL6NJKNPOF3J7HJBPIS5KODP4RFQKRUB2MPDAC #![no_std]extern crate alloc;use alloc::string::{String, ToString};use core::fmt::Write;use lazy_static::lazy_static;use tracing_core::Subscriber;use tracing_subscriber::Layer;use uart_16550::SerialPort;use x86_64::instructions::interrupts;lazy_static! {pub static ref SERIAL1: spin::Mutex<SerialPort> = {let mut serial_port = unsafe { SerialPort::new(0x3F8) };serial_port.init();spin::Mutex::new(serial_port)};}/// Tracing subscriber that does nothing// TODO: figure out how to use standard library so can replace with actual subscriberspub struct MockSubscriber;/// A layer that prints all events to the serial consolepub struct SerialLayer;/// Simple visitor that formats any fields attached to spansstruct PrintVisitor(String);impl<S> Layer<S> for SerialLayerwhereS: tracing_core::Subscriber,{fn on_event(&self,event: &tracing_core::Event<'_>,_ctx: tracing_subscriber::layer::Context<'_, S>,) {let metadata = event.metadata();let mut msg = metadata.level().to_string();// Attach any location contextif let Some(location) = metadata.file().or(metadata.module_path()) {msg.push(' ');msg.push_str(location);if let Some(line) = metadata.line() {msg.push(':');msg.push_str(&line.to_string());}}let mut visitor = PrintVisitor(String::new());event.record(&mut visitor);msg.push_str(&visitor.0);msg.push('\n');interrupts::without_interrupts(|| {SERIAL1.lock().write_str(&msg).expect("Printing to serial failed");});}}impl tracing::field::Visit for PrintVisitor {fn record_debug(&mut self, field: &tracing_core::Field, value: &dyn core::fmt::Debug) {self.0.push(' ');if field.name() != "message" {self.0.push_str(field.name());self.0.push('=');}write!(self.0, "{:#?}", value).unwrap();}}impl Subscriber for MockSubscriber {fn enabled(&self, _metadata: &tracing_core::Metadata<'_>) -> bool {true}fn new_span(&self, _span: &tracing_core::span::Attributes<'_>) -> tracing_core::span::Id {tracing_core::span::Id::from_u64(0)}fn record(&self, _span: &tracing_core::span::Id, _values: &tracing_core::span::Record<'_>) {()}fn record_follows_from(&self,_span: &tracing_core::span::Id,_follows: &tracing_core::span::Id,) {()}fn event(&self, _event: &tracing_core::Event<'_>) {()}fn enter(&self, _span: &tracing_core::span::Id) {()}fn exit(&self, _span: &tracing_core::span::Id) {()}}
[package]name = "tracing_serial"version = "0.1.0"edition = "2021"[dependencies]lazy_static = { version = "1.4.0", features = ["spin_no_std"] }spin = "0.9.8"tracing = { version = "0.1.40", default-features = false }tracing-core = { version = "0.1.32", default-features = false }tracing-subscriber = { version = "0.3.18", default-features = false, features = ["alloc",] }uart_16550 = "0.3.0"x86_64 = "0.14.11"
tracing_serial = { path = "../tracing_serial" }
name = "tracing-subscriber"version = "0.3.18"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"dependencies = ["tracing-core",][[package]]name = "tracing_serial"version = "0.1.0"dependencies = ["lazy_static","spin 0.9.8","tracing","tracing-core","tracing-subscriber","uart_16550","x86_64",][[package]]name = "uart_16550"version = "0.3.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "6dc00444796f6c71f47c85397a35e9c4dbf9901902ac02386940d178e2b78687"dependencies = ["bitflags 1.3.2","rustversion","x86",][[package]]