transcribe_cpp/logging.rs
1//! Routing the native log sink into the [`log`] crate facade.
2//!
3//! Call [`init_logging`] once at process startup (before loading any model) to
4//! send every library and ggml diagnostic through `log` (and thus to whatever
5//! `env_logger`/`tracing-log`/etc. the application installed). This matches the
6//! C contract: `transcribe_log_set` is a once-at-startup global.
7
8use std::ffi::CStr;
9
10use transcribe_cpp_sys as sys;
11
12/// The C log callback: map the level and forward the message to `log`.
13extern "C" fn log_trampoline(
14 level: sys::transcribe_log_level,
15 msg: *const std::os::raw::c_char,
16 _userdata: *mut std::os::raw::c_void,
17) {
18 if msg.is_null() {
19 return;
20 }
21 // SAFETY: `msg` is a NUL-terminated string valid for this call.
22 let text = unsafe { CStr::from_ptr(msg) }.to_string_lossy();
23 let text = text.trim_end_matches('\n');
24 use sys::transcribe_log_level as L;
25 let level = match level {
26 L::TRANSCRIBE_LOG_LEVEL_ERROR => log::Level::Error,
27 L::TRANSCRIBE_LOG_LEVEL_WARN => log::Level::Warn,
28 L::TRANSCRIBE_LOG_LEVEL_DEBUG => log::Level::Debug,
29 // INFO and CONT (continuation fragments) both surface at info.
30 L::TRANSCRIBE_LOG_LEVEL_INFO | L::TRANSCRIBE_LOG_LEVEL_CONT => log::Level::Info,
31 // NONE or any unknown level: drop.
32 _ => return,
33 };
34 log::log!(target: "transcribe_cpp", level, "{text}");
35}
36
37/// Route native + ggml diagnostics into the [`log`] crate. Call once at
38/// startup, before loading models.
39pub fn init_logging() {
40 // SAFETY: install-once-at-startup is the supported usage model.
41 unsafe { sys::transcribe_log_set(Some(log_trampoline), std::ptr::null_mut()) };
42}
43
44/// Silence the native library entirely (drops both library and ggml messages,
45/// including the stderr default). Call once at startup.
46pub fn disable_logging() {
47 unsafe { sys::transcribe_log_set(None, std::ptr::null_mut()) };
48}