使用tracing_subscriber的info_span!结合Axum时触发panic问题求助
问题
尝试在Axum中结合tracing与tracing_subscriber实现JSON格式日志输出,访问接口时触发panic。
代码片段
主函数
fn main() -> Result<(), io::Error> { let rt = runtime::Builder::new_current_thread() .enable_io() .enable_time() .build()?; tracing_subscriber::fmt().event_format(format().json()).init(); if let Err(e) = rt.block_on(axum_main()) { e.source(); } Ok(()) }
axum_main函数
let app: Router<()> = Router::new().route( "/", routing::get(|| { async { tracing::info!("wowo here"); "HELLO,world" }.instrument(tracing::info_span!("hello_span")) }), ); let addr: SocketAddr = "192.168.42.200:9090".parse().unwrap(); let socket = TcpSocket::new_v4()?; #[cfg(all(unix, not(target_os = "solaris"), not(target_os = "illumos")))] { socket.set_reuseport(true)?; socket.set_reuseaddr(true)?; } socket.bind(addr)?; let listener = socket.listen(1024)?; let r = axum::serve(listener, app.into_make_service()).await?; Ok(r)
报错信息
thread 'main' panicked at /root/.cargo/registry/src/rsproxy.cn-e3de039b2554c837/tracing-subscriber-0.3.19/src/fmt/format/json.rs:197:49: span 'hello_span' had malformed fields! this is a bug. error: EOF while parsing a value at line 1 column 0 fields: FormattedFields { fields: "", formatter: tracing_subscriber::fmt::format::DefaultFields, was_ansi: true } stack backtrace: 0: rust_begin_unwind at /rustc/4eb161250e340c8f48f66e2b929ef4a5bed7c181/library/std/src/panicking.rs:692:5 1: core::panicking::panic_fmt at /rustc/4eb161250e340c8f48f66e2b929ef4a5bed7c181/library/core/src/panicking.rs:75:14 2: <tracing_subscriber::fmt::format::json::SerializableSpan<Span,N> as serde::ser::Serialize>::serialize at /root/.cargo/registry/src/rsproxy.cn-e3de039b2554c837/tracing-subscriber-0.3.19/src/fmt/format/json.rs:197:49 3: <serde_json::ser::Compound<W,F> as serde::ser::SerializeMap>::serialize_value
补充说明
将tracing_subscriber::fmt().event_format(format().json()).init()替换为tracing_subscriber::fmt().event_format(format().compact()).init()时,运行正常。
Cargo.toml依赖
[dependencies] axum = "0.8.1" tokio = { version = "1.44.1", features = ["macros", "rt"] } tracing = "0.1.41" tracing-subscriber = {version = "0.3.19",features = ["env-filter","chrono","json"]}
解决方案
这个panic是因为tracing-subscriber的JSON事件格式化器和默认的DefaultFields字段格式化器不兼容导致的——默认字段格式化器输出的是文本格式的字段,无法被JSON序列化器解析,空字段场景下直接触发EOF错误。以下两种方法可以解决:
方法一:显式指定JSON专用字段格式化器
在初始化订阅器时,搭配JsonFields代替默认的字段格式化器:
use tracing_subscriber::fmt::format::JsonFields; tracing_subscriber::fmt() .event_format(format().json()) .with_fields(JsonFields::new()) .init();
方法二:使用JSON格式快捷构造
直接调用fmt().json()方法,它会自动配置好兼容的事件和字段格式化器:
tracing_subscriber::fmt().json().init();
内容的提问来源于stack exchange,提问作者Stop
相关产品推荐
相关产品推荐

