1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
#![no_std]
//! This is a logging adapter that acts as an implementation of the [log crate] and hands the
//! rendered messages off to the [defmt crate].
//!
//! Using this is generally not recommended: Once the log infrastructure is pulled into a project,
//! Rust's string formatting is brought in, avoiding which is a big part of the point of defmt.
//!
//! However, this can be useful during development, when debugging a particular library (that
//! optionally produces messages through log) on a platform for which a defmt output has already
//! been established.
//!
//! [log crate]: https://crates.io/crates/log
//! [defmt crate]: https://crates.io/crates/defmt
//!
//! ### Maturity
//!
//! The current implementation of this takes a huge amount of shortcuts: not only does it not
//! convert log levels, it also hardwires some to the most verbose level, discards lots of
//! information that would otherwise be available, and uses a fixed size buffer.
//!
//! Future iterations of this crate are expected to address these on demand; for example, this
//! could gain a build time configuration mechanism for the maximum expected length, or an `alloc`
//! feature that renders the log messages to a `Vec` instead of a `heapless::Vec` before handing
//! them off to defmt as a slice.
//!
//! The crate will likely introduce such features (altering its behavior) without declaring
//! breaking changes; users are advised to configure their error levels to match which messages
//! they expect to see.
/// Set up log output to be forwarded to defmt
///
/// If the global logger can not be set, this fails silently (in the API sense), but does report to
/// defmt.
pub fn setup() {
struct DefmtLogger;
impl log::Log for DefmtLogger {
fn enabled(&self, _: &log::Metadata) -> bool {
true
}
fn log(&self, record: &log::Record) {
use core::fmt::Write;
let mut rendered = heapless::Vec::<u8, 200>::new();
match write!(rendered, "{}", record.args()) {
Ok(()) => defmt::info!("{}", core::str::from_utf8(&rendered).unwrap()),
Err(_) => defmt::info!(
"{:?}...",
core::str::from_utf8(&rendered).map_err(|_| "Truncated at UTF-8 boundary")
),
}
}
fn flush(&self) {}
}
if log::set_logger(&DefmtLogger).is_err() {
defmt::error!("Could not log::set_logger, continuing without output from there");
} else {
defmt::info!("Should be up now");
}
log::set_max_level(log::LevelFilter::Debug);
}