This PR implements an alternative approach to disabling/enabling logging in crates. Currently we use Cargo features.
This PR removes the need for those Cargo features and replaces them with the env variable: DEFMT_LOG
.
The DEFMT_LOG
env var specifies which crates should emit defmt logs and at which level. Its syntax is the same as the syntax used by the env_logger
crate.
~~The DEFMT_LOG
env var parser currently rejects paths that include modules: so DEFMT_LOG=krate=info
is OK, but DEFMT_LOG=krate::module=info
is rejected. This is intentional and should let us accept module paths and filter based on modules in the future (as in add module support in a backwards compatible fashion).~~ No longer true, DEFMT_LOG
now supports module paths.
One of the main advantages of DEFMT_LOG
is that allows filtering logs with module level granularity. The current Cargo features based approach is more coarse grained and only supports enabling / disabling entire crates.
NOTE this is a target side emit filter and orthogonal to the host side display filter proposed in knurling-rs/probe-run#74. Disabling logs with the target filter makes the target program smaller (, maybe also slightly faster) and it reduces the amount of data sent from the target to the host. Disabling logs with the host filter does not change the target program at all not it changes the amount of data transmitted from the target to the host.
Changing the value of the DEFMT_LOG
env var causes all crates that transitively depend on the defmt_macros
crate to be recompiled.
Example usage:
$ bat src/bin/hello.rs
fn main() -> ! {
defmt::info!("hello");
foo::foo();
bar::bar();
app::exit()
}
mod foo {
pub fn foo() {
defmt::info!("foo");
}
}
mod bar {
pub fn bar() {
defmt::info!("bar");
}
}
$ DEFMT_LOG=hello::foo cargo r --bin hello
0 INFO foo
└─ hello::foo::foo @ src/bin/hello.rs:16
$ DEFMT_LOG=hello::bar cargo r --bin hello
0 INFO bar
└─ hello::bar::bar @ src/bin/hello.rs:22
$ DEFMT_LOG=hello::foo,hello::bar cargo r --bin hello
0 INFO foo
└─ hello::foo::foo @ src/bin/hello.rs:16
1 INFO bar
└─ hello::bar::bar @ src/bin/hello.rs:22
$ DEFMT_LOG=hello cargo r --bin hello
0 INFO hello
└─ hello::__cortex_m_rt_main @ src/bin/hello.rs:8
1 INFO foo
└─ hello::foo::foo @ src/bin/hello.rs:16
2 INFO bar
└─ hello::bar::bar @ src/bin/hello.rs:22
$ rg '\[features' Cargo.toml || echo no Cargo features
no Cargo features
how to test this
as this is not even merged into the main
branch and breaking changes (with respect to defmt v0.2.0) have landed into defmt
, the whole process is quite involved
- install a
probe-run
that uses the decoder in this branch
$ git clone https://github.com/knurling-rs/probe-run
$ cd probe-run
$ # change the `#[dependencies]` section
$ edit Cargo.toml
colored = "2.0"
-defmt-decoder = { version = "=0.2.2", features = ['unstable'] }
+defmt-decoder = { git = "https://github.com/knurling-rs/defmt", branch = "env-filter", features = ['unstable'] }
difference = "2.0"
$ cargo install --path .
- use
[patch.crates-io]
in Cargo.toml
(the one in the root of the workspace) to use the git version of defmt
instead of v0.2.x. The app-template
already includes this section in its Cargo.toml
[patch.crates-io]
defmt = { git = "https://github.com/knurling-rs/defmt", branch = "env-filter" }
defmt-rtt = { git = "https://github.com/knurling-rs/defmt", branch = "env-filter" }
defmt-test = { git = "https://github.com/knurling-rs/defmt", branch = "env-filter" }
panic-probe = { git = "https://github.com/knurling-rs/defmt", branch = "env-filter" }
IMPORTANT use branch = "env-filter"
instead of rev = "somehash"
- set the
PROBE_RUN_IGNORE_VERSION
env variable before you run your firmware e.g.
$ PROBE_RUN_IGNORE_VERSION=1 cargo run --bin hello
- try setting / changing the value of the
DEFMT_LOG
env variable!
$ export PROBE_RUN_IGNORE_VERSION=1
$ DEFMT_LOG=hello=trace cargo run --bin hello
0 INFO Hello, world!
└─ hello::__cortex_m_rt_main @ src/bin/hello.rs:8
As there's other breaking-change work currently ongoing (#508) I plan to leave this work on hold for now -- but will be answering to feedback! -- and resume it when that's concluded.
Unresolved questions
- rename
DEFMT_LOG
to DEFMT_CAPTURE
or DEFMT_TARGET_CAPTURE
? if we keep the DEFMT_LOG
name, what should we name the env var to be used in knurling-rs/probe-run#74?
TODO list
- [x] RFC approval
- [x] address inline TODO comments
- [x] support log level without module path e.g.
DEFMT_LOG=info
- [x] support the
off
pseudo log-level (disables logging)
- [x] fix module path handling so that
DEFMT_LOG=krate::module
doesn't match krate::module1
, krate::module2
, etc.
- [x] fix CI
- [x] documentation. important changes in behavior to note
closes #183
closes #255
closes #459