日志: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_layer 和 fmt_layer 两个函数字段,允许注入自定义的 tracing_subscriber::Layer。常见用途:
- 把日志同时写到文件
- 按 JSON 格式输出(便于日志采集系统解析)
- 把日志转发到远程日志服务
custom_layer 在 tracing subscriber 构建时调用,返回的 Option<BoxedLayer> 会被叠加到默认层之上。fmt_layer 则允许替换默认的格式化层(比如去掉时间戳)。