-
-
Notifications
You must be signed in to change notification settings - Fork 81
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
Feature: Add defmt println!
macro
#569
Conversation
0e4ac44
to
ba979b5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks generally good, but I'm still not sure what our strategy with log
should be. Perhaps the best way forward is to not funnel defmt logs through log
and remove that code?
#[proc_macro] | ||
#[proc_macro_error] | ||
pub fn println(args: TokenStream) -> TokenStream { | ||
function_like::println::expand(args) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason you couldn't reuse log::expand
like the other logging macros? (if so, please add a comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I based it on function write::expand
which is simlar, println::expand
does not check feature flags and sets a different interned string. But I think both versions could be made work in log::expand
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, that makes sense. Yeah, would be good to merge the logic together.
decoder/src/log.rs
Outdated
.module_path(module_path) | ||
.file(file) | ||
.line(line) | ||
.build(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since you don't call .level(...)
here, which level will end up in the Record
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, looks like info
: https://docs.rs/log/0.4.14/src/log/lib.rs.html#1157
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The alternative is to be more transparent, for example:
log::logger().log(
&Record::builder()
.args(format_args!("{}", display))
.level(level.unwrap_or(Level::Trace))
.target(&target)
.module_path(module_path)
.file(file)
.line(line)
.build(),
);
and remove the if else
block completely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's better to be consistent with the underlying default level in log
, therefore the call is now .level(level.unwrap_or(Level::Info)
This feature still requires a bit of writing in the defmt book so that users know about how & when to use this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code LGTM
Still not sure what the best way to proceed with the log
interop code is. I'm thinking that deleting it (and handling defmt frames manually) might be the best way forward, otherwise downstream consumers will have println!
converted to INFO
-level logs, which is kinda wrong.
decoder/src/log.rs
Outdated
crate::Level::Info => Some(Level::Info), | ||
crate::Level::Warn => Some(Level::Warn), | ||
crate::Level::Error => Some(Level::Error), | ||
crate::Level::Println => None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we keep the fallback to Info
, this branch could just be => Level::Info
and we'd remove the Option
I have not looked at the PR but wanted to comment on these:
I agree with this.
The I think a "stable" |
fb80fec
to
2e04bab
Compare
* fix a few lint issues * export `println` macro * add `Tag` variant `Println` * add `expand` function for `println` macro
* rename log level `None` to `Println` * refactor `println` call to use `log::expand` logic * refactor `if else` block to log text
decoder/src/log.rs
Outdated
@@ -75,8 +75,7 @@ impl<'a> DefmtRecord<'a> { | |||
} | |||
|
|||
let timestamp = &target[DEFMT_TARGET_MARKER.len()..]; | |||
|
|||
Some(Self { | |||
(Self{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this compile? the return type is an option but this no longer has the Some
constructor
@@ -210,7 +210,7 @@ fn tests_impl(args: TokenStream, input: TokenStream) -> parse::Result<TokenStrea | |||
test.func.sig.ident | |||
); | |||
quote_spanned! { | |||
test.func.sig.ident.span() => defmt::info!(#message, __defmt_test_number, __DEFMT_TEST_COUNT); | |||
test.func.sig.ident.span() => defmt::println!(#message, __defmt_test_number, __DEFMT_TEST_COUNT); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
macros/src/function_like/println.rs
Outdated
quote!({ | ||
match (#(&(#formatting_exprs)),*) { | ||
(#(#patterns),*) => { | ||
defmt::export::istr(&#format_tag); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should follow the acquire - release pattern used in the log macros, including the header
call. the main difference between the two will be that tag used to constructor the header (there's a make_istr
call in the expansion I believe)
2e04bab
to
049e93c
Compare
This is similar to the `function_like::log::expand` function now.
The `println` macro uses similar logic as the logging macros. When creating a new log frame the log level is optional now, adjusting for the case when a `Frame` is generated from a `println` call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes look good to me. It's not clear to me, though, what's the output when timestamps are enabled. Could you extend the timestamp
snapshot test to include a defmt::println!
call?
The other thing that's not obvious from here is whether probe-run
will also show the source code location for defmt::println!
statements. Including the location would not be standard but certainly useful. I think either way is fine for now personally; same thing for the timestamps.
* refactor `print_location` to take separate arguments instead of a log record
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks great! feel free to send it to bors with the inline nit addressed 🚀
bors r+ |
Build succeeded: |
This PR addresses #541, adding a
defmt::println!
macro to always log content irrespective of a log level.This changes the
level
property inFrame
struct to be ofOption
type, which requires a number of refactorings to handle both ways to log, either using the log macros (e.g.defmt::info!
) or using thedefmt::println!
macro.The addition of the
defmt::println
macro should not break existing functionality.