Rust in Everything
基于 tracing 0.1.44

常见坑

每一章对着一个报错或一个现象:先用最小的程序把它复现出来(编译错误引用 rustc 1.99.0 的原文),再到源码里找它从哪一行来,最后给出修法和检查办法。机制在前面章节讲过的,这里只链过去,不再重复。

  1. Unable to install global subscriber:init 第二次调用时 panic,两种入口两种前缀;测试里每个测试都 init;try_init 的错误可能是全局 subscriber 没装上,也可能是装上了、只是 log 那边被占了,let _ = 把两者一起吞掉。
  2. 一条日志都没有:没装 subscriber;let _ = set_default(..) 的守卫当场 drop;set_default 只管当前线程,tokio 多线程运行时里 spawn 出去的任务什么都不打。
  3. RUST_LOG 设了不生效:my-app=debug 对不上 target my_app,连 ERROR 都没了;逗号后的空格让一段指令解析失败;空的 RUST_LOG= 让 try_from_default_env 返回一个什么都不放行的过滤器。
  4. 跨 .await 持有 span.enter():日志挂到别的 span 上;clippy 默认不报,要配 await_holding_invalid_type;改用 .instrument(span)。
  5. release 构建里 debug! 全部消失:某个依赖开了 release_max_level_*,feature 合并后对整个程序生效。
  6. #[instrument] 报 doesn't implement Debug:参数默认按 Debug 记录,用 skip / skip_all;err 要求 Display。
  7. #[instrument] 的 target 和 parent 一起写报错:tracing-attributes 0.1.31 重复检查写错了字段,换个参数顺序可以绕过。
  8. Span::record 没有效果:字段没在创建 span 时声明,要先写成 field::Empty。
  9. 文件记 debug、终端记 info,结果两边一样:.with(filter) 是全局过滤,要用 layer.with_filter(..)。
  10. 日志重复:tracing 开了 log-always 又装了 LogTracer。
  11. tracing-appender 日志全丢:non_blocking 返回的 WorkerGuard 被立刻 drop,进程退出前缓冲里的日志没写完。
  12. 测试里的日志:fmt().init() 写 stdout,绕过 libtest 的输出捕获;with_test_writer() 才走 print!。
flowchart TB
  setup["装 subscriber 时"] --> p1["1 init 两次"]
  setup --> p2["2 一条都没有"]
  setup --> p10["10 日志重复"]
  setup --> p11["11 appender 丢日志"]
  setup --> p12["12 测试里的日志"]
  gate["过滤的几道门"] --> p3["3 RUST_LOG"]
  gate --> p5["5 release 无 debug"]
  gate --> p9["9 过滤对所有层"]
  spanline["span 主线"] --> p4["4 跨 await 持有"]
  spanline --> p8["8 record 无效"]
  compile["编译期"] --> p6["6 instrument Debug"]
  compile --> p7["7 target 与 parent"]
  p1 --> p2
  p1 --> p12

前两类是事件主线的两端出了问题:一头是 Dispatch 没装对,事件根本没有去处;另一头是某道门把它挡住了。图里两条额外的线:第 1 个里被 let _ = 吞掉的 try_init 错误,常常就是第 2 个的原因;测试里的 init 冲突(第 1 个)和输出不被捕获(第 12 个)是同一段测试代码的两个问题。读之前最好先读过 Dispatch:全局与线程局部、级别过滤的几道门 和 EnvFilter。

💬 关联讨论

发起讨论
加载中...