是否可以在编译时更改应用程序的日志级别?

Pet*_*all 5 logging rust rust-cargo

我不想在运行时依赖于环境变量,而是想编译一个调试或发布版本,其中完全删除了非错误日志消息。

是否可以Cargo.toml通过或通过cargo/ rustc命令行参数更改应用程序的日志级别?

She*_*ter 3

我不相信日志箱具有完全内置的所请求的功能。

一种方法可以静态设置日志记录级别。如果您log使用这些 Cargo 功能中的任何一个来编译 crate,日志级别将在此时受到限制:

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

您可以release_在非发布版本中放弃相同的功能。

优化器可能会看到这个静态值并删除不可能的代码。如果发生这种情况,那么您应该可以走了!

如果您想绝对确定,您可以通过使用 Cargo 功能创建您自己的条件编译来近似它。这是一个简单的示例,它将打印或不打印值,具体取决于是否启用该功能:

#[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!");
}
Run Code Online (Sandbox Code Playgroud)

这有相应的节Cargo.toml

[features]
slim = []
Run Code Online (Sandbox Code Playgroud)

当您编译/运行程序时,您可以选择有哪些功能:

#[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!");
}
Run Code Online (Sandbox Code Playgroud)

然后只需将记录器宏包装在您自己的条件编译宏中即可:

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

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

运行产量:

[features]
slim = []
Run Code Online (Sandbox Code Playgroud)

对于一些社论,我不同意这样做。当某些东西发生故障时,就是您希望能够记录某些内容的时候。在大多数情况下,我认为布尔值检查的成本不足以保证这一点。我还怀疑在大多数情况下您是否会拥有兆字节的文本。

总有例外 - 也许您需要在紧密循环中记录某些内容,或者您​​必须进行编译以适应空间有限的微控制器。

请注意,我并没有尝试将日志消息的剥离与“发布”构建的概念结合起来。我保证有时您会想要包含这些消息的发布版本,因此最好使这两个想法正交。

  • 我想指出,至少确保调试日志永远不会进入发布二进制文件是很常见的。大多数日志记录的问题是格式化需要大量代码,虽然这些代码通常不会动态执行,但它仍然会影响优化器的决策。日志记录的存在可能会抑制内联、升级到寄存器等...... (3认同)