Skip to content

[WIP] Add support for runtime filtering #947

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 18 additions & 10 deletions defmt/src/export/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,20 +209,28 @@ pub fn display(val: &dyn core::fmt::Display) {
}

#[inline(never)]
pub unsafe fn acquire_and_header(s: &Str) {
acquire();
istr(s);
timestamp(make_formatter());
#[must_use]
pub unsafe fn check_acquire_and_header(s: &Str) -> bool {
if s.level_above_global_log_level() {
acquire();
istr(s);
timestamp(make_formatter());
true
} else {
false
}
}

#[inline(never)]
pub fn acquire_header_and_release(s: &Str) {
// safety: will be released a few lines further down
unsafe { acquire() };
istr(s);
timestamp(make_formatter());
// safety: acquire() was called a few lines above
unsafe { release() };
if s.level_above_global_log_level() {
// safety: will be released a few lines further down
unsafe { acquire() };
istr(s);
timestamp(make_formatter());
// safety: acquire() was called a few lines above
unsafe { release() };
}
}

struct FmtWrite;
Expand Down
22 changes: 22 additions & 0 deletions defmt/src/formatter.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::{get_global_log_level, IdRanges, LogLevel};
use core::marker::PhantomData;

/// Handle to a defmt logger.
Expand All @@ -14,3 +15,24 @@ pub struct Str {
/// 16-bit address
pub(crate) address: u16,
}

impl Str {
/// If the interned string is a log message, returns whether its level is above the global log level.
/// If the interned string is not a log message, returns `false`.
/// See [`set_global_log_level`] to change the log level
pub(crate) fn level_above_global_log_level(&self) -> bool {
let ranges = IdRanges::get();
if self.address >= ranges.trace.start && self.address < ranges.error.end {
let min_id = match get_global_log_level() {
LogLevel::Trace => ranges.trace.start,
LogLevel::Debug => ranges.debug.start,
LogLevel::Info => ranges.info.start,
LogLevel::Warn => ranges.warn.start,
LogLevel::Error => ranges.error.start,
};
self.address >= min_id
} else {
false
}
}
}
34 changes: 34 additions & 0 deletions defmt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,40 @@ pub fn flush() {
}
}

/// Log Level of a defmt message
/// Use `set_global_log_level` to set the global log level used to filter messages at runtime.
/// Note: Use the environment variable `DEFMT_LOG` to disable certain log levels already at compile time
#[repr(u8)]
pub enum LogLevel {
/// Trace level
Trace = 0,
/// Debug level
Debug = 1,
/// Info level
Info = 2,
/// Warn level
Warn = 3,
/// Error level
Error = 4,
}

static LOG_LEVEL: core::sync::atomic::AtomicU8 =
core::sync::atomic::AtomicU8::new(LogLevel::Trace as u8);

/// Sets the global log level used to filter messages at runtime.
/// Messages below the passed level will never reach the defmt `global_logger`
/// Note: Use the environment variable `DEFMT_LOG` to disable certain log levels already at compile time
pub fn set_global_log_level(min_level: LogLevel) {
LOG_LEVEL.store(min_level as u8, core::sync::atomic::Ordering::Relaxed);
}

/// Gets the global log level used to filter messages at runtime.
/// Messages below the returned level will never reach the defmt `global_logger`
pub fn get_global_log_level() -> LogLevel {
let level = LOG_LEVEL.load(core::sync::atomic::Ordering::Relaxed);
unsafe { core::mem::transmute(level) }
}

#[cfg(not(feature = "unstable-test"))]
#[doc(hidden)]
pub struct IdRanges {
Expand Down
9 changes: 5 additions & 4 deletions macros/src/function_like/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,11 @@ pub(crate) fn expand_parsed(level: Level, args: Args) -> TokenStream2 {
} else {
quote!(
// safety: will be released a few lines further down
unsafe { defmt::export::acquire_and_header(&#header); };
#(#exprs;)*
// safety: acquire() was called a few lines above
unsafe { defmt::export::release() }
if( unsafe { defmt::export::check_acquire_and_header(&#header) }) {
#(#exprs;)*
// safety: acquire() was called a few lines above
unsafe { defmt::export::release() }
}
)
};

Expand Down
9 changes: 5 additions & 4 deletions macros/src/function_like/println.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,11 @@ pub(crate) fn expand_parsed(args: Args) -> TokenStream2 {
} else {
quote!(
// safety: will be released a few lines further down
unsafe { defmt::export::acquire_and_header(&#header); };
#(#exprs;)*
// safety: acquire() was called a few lines above
unsafe { defmt::export::release() }
if (unsafe { defmt::export::check_acquire_and_header(&#header) }){
#(#exprs;)*
// safety: acquire() was called a few lines above
unsafe { defmt::export::release() }
}
)
};
quote!({
Expand Down
Loading