Next Generation WASM Microkernel Operating System
at trap_handler 163 lines 5.3 kB view raw
1// Copyright 2025 Jonas Kruckenberg 2// 3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or 4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or 5// http://opensource.org/licenses/MIT>, at your option. This file may not be 6// copied, modified, or distributed except according to those terms. 7 8use log::Record; 9use spin::LazyLock; 10use tracing::field; 11use tracing_core::{Callsite, Collect, Event, Kind, Level, Metadata, dispatch, identify_callsite}; 12 13impl log::Log for super::Subscriber { 14 fn enabled(&self, metadata: &log::Metadata) -> bool { 15 if let Some(level_filter) = self.max_level_hint() { 16 loglevel_to_level(metadata.level()) <= level_filter 17 } else { 18 false 19 } 20 } 21 22 fn log(&self, record: &Record) { 23 dispatch::get_default(|dispatch| { 24 let (cs, keys, meta) = loglevel_to_callsite(record.level()); 25 let cs_id = identify_callsite!(cs); 26 27 let filter_meta = Metadata::new( 28 "log record", 29 record.target(), 30 loglevel_to_level(record.level()), 31 None, 32 None, 33 None, 34 field::FieldSet::new(FIELD_NAMES, cs_id), 35 Kind::EVENT, 36 ); 37 38 if !dispatch.enabled(&filter_meta) { 39 return; 40 } 41 42 let log_module = record.module_path(); 43 let log_file = record.file(); 44 let log_line = record.line(); 45 46 let module = log_module.as_ref().map(|s| s as &dyn field::Value); 47 let file = log_file.as_ref().map(|s| s as &dyn field::Value); 48 let line = log_line.as_ref().map(|s| s as &dyn field::Value); 49 50 dispatch.event(&Event::new( 51 meta, 52 &meta.fields().value_set(&[ 53 (&keys.message, Some(record.args() as &dyn field::Value)), 54 (&keys.target, Some(&record.target())), 55 (&keys.module, module), 56 (&keys.file, file), 57 (&keys.line, line), 58 ]), 59 )); 60 }); 61 } 62 63 fn flush(&self) {} 64} 65 66struct Fields { 67 message: field::Field, 68 target: field::Field, 69 module: field::Field, 70 file: field::Field, 71 line: field::Field, 72} 73 74static FIELD_NAMES: &[&str] = &[ 75 "message", 76 "log.target", 77 "log.module_path", 78 "log.file", 79 "log.line", 80]; 81 82impl Fields { 83 fn new(cs: &'static dyn Callsite) -> Self { 84 let fieldset = cs.metadata().fields(); 85 let message = fieldset.field("message").unwrap(); 86 let target = fieldset.field("log.target").unwrap(); 87 let module = fieldset.field("log.module_path").unwrap(); 88 let file = fieldset.field("log.file").unwrap(); 89 let line = fieldset.field("log.line").unwrap(); 90 Fields { 91 message, 92 target, 93 module, 94 file, 95 line, 96 } 97 } 98} 99 100fn loglevel_to_level(level: log::Level) -> Level { 101 match level { 102 log::Level::Error => Level::ERROR, 103 log::Level::Warn => Level::WARN, 104 log::Level::Info => Level::INFO, 105 log::Level::Debug => Level::DEBUG, 106 log::Level::Trace => Level::TRACE, 107 } 108} 109 110macro_rules! log_cs { 111 ($level:expr, $cs:ident, $meta:ident, $ty:ident) => { 112 struct $ty; 113 static $cs: $ty = $ty; 114 static $meta: Metadata<'static> = Metadata::new( 115 "log event", 116 "log", 117 $level, 118 ::core::option::Option::None, 119 ::core::option::Option::None, 120 ::core::option::Option::None, 121 ::tracing_core::field::FieldSet::new( 122 FIELD_NAMES, 123 ::tracing_core::identify_callsite!(&$cs), 124 ), 125 ::tracing_core::metadata::Kind::EVENT, 126 ); 127 128 impl tracing_core::callsite::Callsite for $ty { 129 fn set_interest(&self, _: ::tracing_core::Interest) {} 130 fn metadata(&self) -> &'static Metadata<'static> { 131 &$meta 132 } 133 } 134 }; 135} 136 137log_cs!(Level::TRACE, TRACE_CS, TRACE_META, TraceCallsite); 138log_cs!(Level::DEBUG, DEBUG_CS, DEBUG_META, DebugCallsite); 139log_cs!(Level::INFO, INFO_CS, INFO_META, InfoCallsite); 140log_cs!(Level::WARN, WARN_CS, WARN_META, WarnCallsite); 141log_cs!(Level::ERROR, ERROR_CS, ERROR_META, ErrorCallsite); 142 143static TRACE_FIELDS: LazyLock<Fields> = LazyLock::new(|| Fields::new(&TRACE_CS)); 144static DEBUG_FIELDS: LazyLock<Fields> = LazyLock::new(|| Fields::new(&DEBUG_CS)); 145static INFO_FIELDS: LazyLock<Fields> = LazyLock::new(|| Fields::new(&INFO_CS)); 146static WARN_FIELDS: LazyLock<Fields> = LazyLock::new(|| Fields::new(&WARN_CS)); 147static ERROR_FIELDS: LazyLock<Fields> = LazyLock::new(|| Fields::new(&ERROR_CS)); 148 149fn loglevel_to_callsite( 150 level: log::Level, 151) -> ( 152 &'static dyn Callsite, 153 &'static Fields, 154 &'static Metadata<'static>, 155) { 156 match level { 157 log::Level::Trace => (&TRACE_CS, &*TRACE_FIELDS, &TRACE_META), 158 log::Level::Debug => (&DEBUG_CS, &*DEBUG_FIELDS, &DEBUG_META), 159 log::Level::Info => (&INFO_CS, &*INFO_FIELDS, &INFO_META), 160 log::Level::Warn => (&WARN_CS, &*WARN_FIELDS, &WARN_META), 161 log::Level::Error => (&ERROR_CS, &*ERROR_FIELDS, &ERROR_META), 162 } 163}