Skip to content

日志:tracing 宏与 LogPlugin

Bevy 的日志建立在 tracing crate 之上。五个宏按严重程度从低到高排列:

典型用途
trace!最细粒度,逐帧逐实体的跟踪信息
debug!开发期调试,正常运行时不需要
info!一般运行状态,启动、完成、关键事件
warn!不致命但值得注意的异常
error!出了问题,需要排查
rust
use bevy::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .add_systems(Update, log_demo)
        .run();
}

fn setup() {
    info!("应用启动——日志系统就绪");
}

fn log_demo(mut frame: Local<u32>) {
    *frame += 1;
    if *frame == 1 {
        info!("第一帧:一切正常");
    }
    if *frame == 100 {
        warn!("第 100 帧:有点慢了,检查一下性能");
    }
    if *frame == 500 {
        error!("第 500 帧:还在跑?这不对劲");
    }
    if *frame == 10 {
        debug!("第 10 帧:调试信息,仅 development 构建可见");
    }
    if *frame == 1 {
        trace!("第 1 帧:最细粒度的跟踪日志");
    }
}

Listing 33-1:五个日志宏——从 info 到 trace

默认情况下,DefaultPlugins 里的 LogPlugin 会把 info 及以上级别输出到 stderr。debug!trace! 在 release 构建中默认被编译期裁剪(通过 log crate 的 feature flags),不产生运行时开销。

LogPlugin 配置

LogPlugin 有两个关键字段:

  • level:最低输出级别。设为 Level::DEBUG 就能看到 debug! 的输出
  • filter:基于 tracing_subscriber::EnvFilter 的字符串,可以按模块路径精细过滤
rust
use bevy::log::{Level, LogPlugin};
use bevy::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins.set(LogPlugin {
            level: Level::DEBUG,
            filter: "wgpu=error,bevy_render=warn,ch33_logging=debug".to_string(),
            ..default()
        }))
        .add_systems(Startup, setup)
        .add_systems(Update, noisy_system)
        .run();
}

fn setup() {
    info!("自定义日志配置已生效");
}

fn noisy_system(mut frame: Local<u32>) {
    *frame += 1;
    let f = *frame;
    if f % 60 == 0 {
        debug!("每 60 帧打印一次调试信息,frame = {}", f);
    }
}

Listing 33-2:自定义 LogPlugin——只让目标 crate 输出 debug

filter 字符串的语法是 模块路径=级别,逗号分隔多条规则。上例中:

  • wgpu=error:wgpu 只报 error(减少噪音)
  • bevy_render=warn:渲染模块报 warn 及以上
  • ch33_logging=debug:本章示例 crate 报 debug 及以上

也可以用环境变量 RUST_LOG 覆盖 filter,运行时动态调整:

bash
RUST_LOG="ch33_logging=trace,wgpu=off" cargo run --example listing-33-02

自定义日志层

LogPlugin 还提供 custom_layerfmt_layer 两个函数字段,允许注入自定义的 tracing_subscriber::Layer。常见用途:

  • 把日志同时写到文件
  • 按 JSON 格式输出(便于日志采集系统解析)
  • 把日志转发到远程日志服务

custom_layer 在 tracing subscriber 构建时调用,返回的 Option<BoxedLayer> 会被叠加到默认层之上。fmt_layer 则允许替换默认的格式化层(比如去掉时间戳)。