
Rerun 宿主语言原生日志集成指南将 Python / C / Rust 标准日志流透明接入 Rerun Viewer【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerunRerun SDK 实现了其所支持宿主语言的原生日志接口允许开发者用 Python 标准库logging、C 的 Loguru、Rust 的logcrate 写出的日志透明地直接流入 Rerun Viewer无需改动业务代码。本文基于仓库文档 integrate-host-loggers.md 与对应的三语言示例讲解每种语言的接入方式、日志级别映射规则与底层实现原理让你把 Rerun 的TextLog与宿主语言日志系统无缝打通。核心思路让原生日志接口成为 Rerun 的输入管道Rerun 的文本日志能力以TextLog原型archetype为核心它的数据模型在 text_log.md 中定义一条日志由必填的text日志正文与推荐的level日志级别组成还可选附带color用于着色。它既可以显示在文本日志视图TextLogView中也可以出现在数据表格视图DataframeView里。文档介绍的“原生日志集成”思路非常直接不要求你改用 Rerun 专用 API 打日志而是让 Rerun SDK 去“实现”宿主语言已有的日志接口。这样程序中凡是通过标准日志通道输出的内容都会被透明地转发为TextLog记录并顺着RecordingStream进入 Rerun Viewer。集成后的数据流可以概括为宿主语言日志调用logging / Loguru / log 宏 │ 由 Rerun 提供的 handler / callback / Logger 捕获 ▼ 日志级别映射为 TextLogLevel │ 记录写入形如 logs/handler/module 的实体路径 ▼ Rerun ViewerTextLog 视图实时显示这一机制的价值在于多模态机器人与视觉应用中日志与传感器数据图像、点云、变换等本就同处一条时间线上把日志也接入 Rerun 后排查问题时可以在同一时间轴上对齐“日志正文”与“可视数据”大幅提升调试效率。三语言示例总览文档对应的完整可运行示例位于 docs/snippets/all/archetypes/ 目录Pythontext_log_integration.pyCtext_log_integration.cppRusttext_log_integration.rs在 snippets.toml 中该示例被声明为同时覆盖 cpp / py / rust 三种语言并特意注明“entity path will differ because the integrations work differently”——即不同语言因为原生日志接口的工作方式不同最终写入的实体路径会有所差异这正是三种方案底层机制不同所致。此外TextLog的类型定义还分布在Rust 类型crates/store/re_sdk_types/src/archetypes/text_log.rsPython 类型rerun_py/rerun_sdk/rerun/archetypes/text_log.pyC 类型rerun_cpp/src/rerun/archetypes/text_log.hppPython通过标准库 logging 的 Handler 接入Python 方案最轻量核心是rerun.LoggingHandler它是一个标准的logging.Handler子类实现在 _logging_handler.py 中。文档示例 text_log_integration.py 完整演示了两种用法。直接记录一条 TextLogimport rerun as rr rr.init(rerun_example_text_log_integration, spawnTrue) # Log a text entry directly rr.log( logs, rr.TextLog(this entry has loglevel TRACE, levelrr.TextLogLevel.TRACE), )rr.log的第一个参数是实体路径此处为logs第二个参数是TextLog原型TextLogLevel提供TRACE/DEBUG/INFO/WARN/ERROR/CRITICAL等预定义级别。挂载 Handler接管标准 logging 通道import logging import rerun as rr rr.init(rerun_example_text_log_integration, spawnTrue) logging.getLogger().addHandler(rr.LoggingHandler(logs/handler)) logging.getLogger().setLevel(-1) logging.info(This INFO log got added through the standard logging interface)要点说明rr.LoggingHandler(path_prefix)接受一个可选的前缀参数作为所有日志实体路径的公共前缀示例中为logs/handler默认无前缀。logging.getLogger().setLevel(-1)将根 logger 的阈值降为负数等价于“不过滤任何级别”保证低级别日志也能进入 Rerun。之后程序中所有通过标准logging接口输出的日志都会自动成为 Rerun 中的TextLog记录。Python 侧级别映射与实体路径的底层实现从 _logging_handler.py 的实现可以看到级别映射表LVL2NAME将 Python 的logging.CRITICAL/ERROR/WARNING/INFO/DEBUG分别映射到TextLogLevel.CRITICAL/ERROR/WARN/INFO/DEBUG注意WARNING映射为WARN。如果遇到用户自定义级别表中查不到会退化为直接用record.levelname字符串构造TextLogLevel这与 Rerun 的TextLogLevel本身是自由字符串类型的设计吻合。实体路径的构成规则为ent_path record.module.replace(., /)即日志来源模块名中的.会被替换为/如模块foo.bar变成foo/bar再叠加可选的前缀最终调用log(ent_path, TextLog(record.getMessage(), levellevel))且注释说明该调用会进入“最合适的 recording”。Rust通过 log crate 的 Logger 接入Rust 侧由rerun::Logger实现它实现了logcrate 的Logtrait源码位于 crates/top/rerun/src/log_integration.rs。文档示例 text_log_integration.rs 演示了完整接入过程。接入示例use rerun::external::log; fn main() - Result(), Boxdyn std::error::Error { let rec rerun::RecordingStreamBuilder::new( rerun_example_text_log_integration, ) .spawn()?; // Log a text entry directly: rec.log( logs, rerun::TextLog::new(this entry has loglevel TRACE) .with_level(rerun::TextLogLevel::TRACE), )?; // Or log via a logging handler: rerun::Logger::new(rec.clone()) // recording streams are ref-counted .with_path_prefix(logs/handler) // You can also use the standard RUST_LOG environment variable! .with_filter(rerun::default_log_filter()) .init()?; log::info!( This INFO log got added through the standard logging interface ); log::logger().flush(); Ok(()) }关键点Logger::new(rec.clone())接收一个RecordingStream的克隆——Rust 侧流是引用计数的因此可以放心复制并交给 Logger 持有。with_path_prefix给所有日志实体路径加上公共前缀示例为logs/handler。with_filter(rerun::default_log_filter())设置过滤规则如不显式调用init()时也会自动从RUST_LOG环境变量解析详见下文。log::logger().flush()在程序退出前刷新缓冲确保日志落盘/送出事实上Logger的Drop实现也会自动flush见 log_integration.rs。底层实现过滤器、路径拼接与级别映射从 log_integration.rs 的源码可以看到完整的实现细节过滤with_filter使用与env_logger兼容的过滤语法解析字符串build_filter解析失败时只会告警并退回到空过滤器不会报错若未显式设置过滤器init()会回退使用re_log::default_log_filter()见 log_integration.rs。全局 loggerinit()会调用log::set_max_level(log::LevelFilter::max())并log::set_boxed_logger从此所有log宏调用都会流经该 Logger注释特别说明过滤按 crate/module 粒度进行因此不设全局过滤上限。实体路径record.metadata().target().replace(::, /)把日志目标的::换成/如my_crate::module变为my_crate/module再与path_prefix拼接。级别映射log_level_to_rerun_level将log::Level的Error/Warn/Info/Debug/Trace一一映射到TextLogLevel的ERROR/WARN/INFO/DEBUG/TRACE见 log_integration.rs。写入对每条记录构造TextLog::new(body).with_level(level)并rec.log(ent_path, ...)写失败时静默忽略.ok()。默认过滤器的取值规则re_log::default_log_filter()实现在 crates/utils/re_log/src/lib.rs的规则是原生非 wasm平台优先读取RUST_LOG环境变量未设置时在 debug 构建下默认debug、release 构建下默认info因为 Rerun 会在 INFO 级别打印关键信息例如rerun-cli托管服务时的 ip:port。Webwasm32平台固定为debugWeb 控制台允许任意过滤。同时会叠加针对若干“过于话痨”的 crate 的内置过滤规则。C通过 Loguru 回调接入C 示例使用 Loguru 日志库#include loguru.hpp通过loguru::add_callback注册回调把 Loguru 的输出桥接到 Rerun。完整代码见 text_log_integration.cpp。回调桥接的核心代码#include loguru.hpp #include rerun.hpp void loguru_to_rerun(void* user_data, const loguru::Message message) { // NOTE: rerun::RecordingStream is thread-safe. const rerun::RecordingStream* rec reinterpret_castconst rerun::RecordingStream*(user_data); rerun::TextLogLevel level; if (message.verbosity loguru::Verbosity_FATAL) { level rerun::TextLogLevel::Critical; } else if (message.verbosity loguru::Verbosity_ERROR) { level rerun::TextLogLevel::Error; } else if (message.verbosity loguru::Verbosity_WARNING) { level rerun::TextLogLevel::Warning; } else if (message.verbosity loguru::Verbosity_INFO) { level rerun::TextLogLevel::Info; } else if (message.verbosity loguru::Verbosity_1) { level rerun::TextLogLevel::Debug; } else if (message.verbosity loguru::Verbosity_2) { level rerun::TextLogLevel::Trace; } else { level rerun::TextLogLevel(std::to_string(message.verbosity)); } rec-log( logs/handler/text_log_integration, rerun::TextLog(message.message).with_level(level) ); }要点user_data指向rerun::RecordingStream示例中通过const_castvoid*(reinterpret_castconst void*(rec))传入注释特别提醒RecordingStream是线程安全的因此回调可以在多线程环境中安全调用rec-log。级别映射覆盖 Loguru 的Verbosity_FATAL/ERROR/WARNING/INFO/1/2分别对应 Rerun 的Critical/Error/Warning/Info/Debug/Trace其余未覆盖的 verbosity 值直接以其数字字符串构造TextLogLevel——这再次印证TextLogLevel是开放字符串类型的设计。主流程与生命周期int main(int argc, char* argv[]) { const auto rec rerun::RecordingStream(rerun_example_text_log_integration); rec.spawn().exit_on_failure(); // Log a text entry directly: rec.log( logs, rerun::TextLog(this entry has loglevel TRACE) .with_level(rerun::TextLogLevel::Trace) ); loguru::add_callback( rerun, loguru_to_rerun, const_castvoid*(reinterpret_castconst void*(rec)), loguru::Verbosity_INFO ); LOG_F( INFO, This INFO log got added through the standard logging interface ); // we need to do this before rec goes out of scope: loguru::remove_callback(rerun); }生命周期注意点loguru::add_callback(rerun, loguru_to_rerun, rec, loguru::Verbosity_INFO)以名为rerun的回调注册并指定最低 verbosity 为Verbosity_INFO。程序结束前必须调用loguru::remove_callback(rerun)注销回调且要在rec析构之前完成否则回调可能引用已销毁的RecordingStream。各语言方案的对比与选用建议维度PythonRustC原生日志接口标准库logginglogcrateLoguru桥接组件rr.LoggingHandlerlogging.Handler子类rerun::Loggerlog::Log实现loguru::add_callback回调实体路径规则前缀 模块名.→/前缀 日志 target::→/代码中硬编码示例为logs/handler/text_log_integration级别映射CRITICAL/ERROR/WARNING/INFO/DEBUG → CRITICAL/ERROR/WARN/INFO/DEBUGError/Warn/Info/Debug/Trace → ERROR/WARN/INFO/DEBUG/TRACEFATAL/ERROR/WARNING/INFO/1/2 → Critical/Error/Warning/Info/Debug/Trace未映射级别用record.levelname原样构造直接透传目标字符串用 verbosity 数字字符串构造由于实体路径构成机制不同snippets.toml 中特意注明该示例的 entity path 在各语言下会不同。选用建议Python 项目直接复用标准logging改动最小一行addHandler即完成接入Rust 项目若已在用log宏Logger可无缝接管全部日志还能沿用RUST_LOG环境变量控制过滤C 项目Loguru 用户可通过回调桥接其他日志库如 spdlog也可参考同样的回调思路自行对接。深入理解 TextLogLevel 与数据落点无论走哪条桥接路径最终都汇入TextLog原型其TextLogLevel组件的定义在 text_log_level_ext.rs 中预定义级别常量CRITICAL灾难性故障、ERROR严重错误、WARN危险情况、INFO有用信息、DEBUG较低优先级信息、TRACE极低优先级、通常非常冗长的信息默认级别为INFOimpl Default它是一个包装Utf8的组件见 text_log_level.rs因此理论上可以承载任意自定义级别字符串。日志写入后在 Rerun 中默认展示于TextLogView也可以在DataframeView中按表格查看配合 Rerun 的时间轴文本日志与图像、点云等数据可在同一时刻对齐观察。若想为不同级别着色可在TextLog上附加可选的color字段参考 text_log.md 的字段定义。小结Rerun 对宿主语言原生日志接口的集成让“日志”与“可视化数据”共享同一条 Rerun 时间线从而在调试多模态数据时获得全局一致的时间上下文。三套方案共用一套TextLog数据模型但桥接方式各不相同Python 用LoggingHandler挂进标准库loggingRust 用Logger实现logcrate 的LogtraitC 通过 Loguru 回调转发。读者可直接以 docs/snippets/all/archetypes/text_log_integration.py、text_log_integration.rs 与 text_log_integration.cpp 为起点将日志无缝接入自己的 Rerun 工作流。【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考