Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
514 views
in Technique[技术] by (71.8m points)

logging - Is it possible to change the log level for an application at compile time?

Rather than rely on environment variables at runtime, I'd like to compile a debug or release version with non-error log messages stripped out completely.

Is it possible to change the log level for an application in the Cargo.toml or via cargo/rustc command line arguments?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I don't believe that the log crate has exactly the requested functionality built in.

There is a way to statically set the logging level. If you compile the log crate with any of these Cargo features, the log level will be capped at that point:

  • release_max_level_off
  • release_max_level_error
  • release_max_level_warn
  • release_max_level_info
  • release_max_level_debug
  • release_max_level_trace

You can drop the release_ off for the same functionality in non-release builds.

It's possible that the optimizer will see this static value and remove code that is impossible. If that happens, then you should be good to go!

If you want to be absolutely certain, you could approximate it by creating your own conditional compilation with Cargo features. Here's a simple example that will print a value or not, depending on whether the feature is enabled:

#[cfg(not(feature = "slim"))]
macro_rules! my_info {
    ($x: expr) => { println!("{:?}", $x) }
}

#[cfg(feature = "slim")]
macro_rules! my_info {
    ($x: expr) => { }
}

fn main() {
    my_info!("Hello, world!");
}

This has a corresponding stanza in Cargo.toml:

[features]
slim = []

And when you compile / run your program, you can pick which features there are:

$ cargo run
     Running `target/debug/log`
"Hello, world!"
$ cargo run --features=slim
     Running `target/debug/log`
$ 

Then it's just a matter of wrapping the logger macros in your own conditionally-compiled macros:

#[cfg(not(feature = "slim"))]
macro_rules! my_info {
    ($($arg: tt)*) => { info!($($arg)*) }
}

#[cfg(feature = "slim")]
macro_rules! my_info {
    ($($arg: tt)*) => { }
}

Running yields:

$ RUST_LOG=info cargo run
     Running `target/debug/log`
INFO:log: Hello, world!
$ RUST_LOG=info cargo run --features=slim
     Running `target/debug/log`
$

For a bit of editorial, I disagree with doing this. When something breaks, that's when you most want the ability to log something. In the majority of cases, I don't believe that the cost of the check of the boolean would be expensive enough to warrant this. I also doubt that you will have megabytes of text in most cases.

There are always exceptions - maybe you need to log something in a tight loop, or you have to compile to fit on a microcontroller with limited space.

Note that I didn't try to couple stripping out the log messages with the concept of a "release" build. I guarantee that there are times you will want a release build with these messages, so it's better to make those two ideas orthogonal.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...