ffgl_core/
log.rs

1//! Used to connect the internal FFGL logging system to your rust code.
2//!
3
4use std::{
5    ffi::{c_char, CString},
6    io,
7    sync::RwLock,
8};
9
10static mut LOADING_LOGGER: std::sync::RwLock<Option<FFGLLogger>> = RwLock::new(None);
11///Type of the logging function the plugin can call
12#[doc(hidden)]
13pub type FFGLLogger = unsafe extern "C" fn(*const c_char) -> ();
14
15struct FFGLWriter;
16
17impl io::Write for FFGLWriter {
18    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
19        let str = String::from_utf8_lossy(buf);
20
21        if let Some(logger) = unsafe { *LOADING_LOGGER.read().unwrap() } {
22            let str = CString::new(str.as_bytes()).expect("Failed to convert to CString");
23            unsafe { logger(str.as_ptr()) };
24        } else {
25            eprintln!("{}", str);
26        }
27
28        Ok(buf.len())
29    }
30
31    fn flush(&mut self) -> io::Result<()> {
32        Ok(())
33    }
34}
35
36pub(crate) fn try_init_default_subscriber() -> Result<(), tracing_subscriber::util::TryInitError> {
37    let env_filter = tracing_subscriber::EnvFilter::builder()
38        .with_default_directive(LevelFilter::INFO.into())
39        .from_env_lossy();
40
41    //try set tracing logger
42    tracing_subscriber::fmt()
43        .with_writer(|| FFGLWriter)
44        .without_time()
45        .with_file(true)
46        .with_line_number(true)
47        .with_env_filter(env_filter)
48        .finish()
49        .try_init()
50}
51
52///Initializes the default subscriber for the logger
53///Will be automatically initialised after [crate::handler::FFGLHandler::init] is called
54pub fn init_default_subscriber() {
55    if let Err(err) = try_init_default_subscriber() {
56        tracing::debug!("Failed to initialize logger: {}", err);
57    }
58}
59
60///Only called by the plugin loader
61#[doc(hidden)]
62pub fn init_logger(logger: FFGLLogger) {
63    unsafe { *LOADING_LOGGER.write().unwrap() = Some(logger) };
64
65    std::panic::set_hook(Box::new(|cause| {
66        tracing::error!("{}", cause);
67    }));
68}
69
70use tracing_subscriber::{filter::LevelFilter, util::SubscriberInitExt};