diff --git a/core/dr-inference-engine/src/session.rs b/core/dr-inference-engine/src/session.rs index fa36f9f..0314b80 100644 --- a/core/dr-inference-engine/src/session.rs +++ b/core/dr-inference-engine/src/session.rs @@ -19,6 +19,9 @@ pub fn build(rung: Rung, role: Role, bytes: &[u8], cfg: &Config) -> ort::Result< // `stack_tensors`) — a panic across the C API, which is an abort. The // app never asked tract for that and does not start now. let mut b = Session::builder()?.with_intra_threads(threads(cfg))?; + if crate::api::runtime().is_native() { + b = with_runtime_log(b)?; + } // A Hexagon session loads the compiled context when there is one and // compiles it from the model when there is not; the engine thread is // what makes the second case rare (§6). @@ -37,6 +40,39 @@ pub fn build(rung: Rung, role: Role, bytes: &[u8], cfg: &Config) -> ort::Result< } } +/// Send the runtime's own messages for this session to `log`, under the +/// target `onnxruntime`, instead of to ONNX Runtime's stdio logger. +/// +/// Its stderr is nowhere once the app is launched from a menu, and what a +/// provider says while it partitions a graph — how many nodes it took, which +/// operator it declined, the library it failed to load — is most of what a +/// failed rung tells you (docs/dev/inference.md §4). The level follows the +/// filter: warnings always, `debug` adds the runtime's info lines (the +/// partition counts), `trace` its verbose ones (every node placement). +fn with_runtime_log( + b: ort::session::builder::SessionBuilder, +) -> ort::Result { + use ort::logging::LogLevel; + let level = if log::log_enabled!(target: "onnxruntime", log::Level::Trace) { + LogLevel::Verbose + } else if log::log_enabled!(target: "onnxruntime", log::Level::Debug) { + LogLevel::Info + } else { + LogLevel::Warning + }; + let forward = |level: LogLevel, _category: &str, _id: &str, location: &str, message: &str| { + let level = match level { + LogLevel::Verbose => log::Level::Trace, + LogLevel::Info => log::Level::Debug, + LogLevel::Warning => log::Level::Warn, + LogLevel::Error | LogLevel::Fatal => log::Level::Error, + }; + log::log!(target: "onnxruntime", level, "{message} ({location})"); + }; + Ok(b.with_logger(std::sync::Arc::new(forward))? + .with_log_level(level)?) +} + /// The intra-op pool: what the config says, else the cores less two for /// the compositor and the decoder (§9). tract ignores it. fn threads(cfg: &Config) -> usize {