flexi_logger icon indicating copy to clipboard operation
flexi_logger copied to clipboard

Writing to `std::fs::File` (or any type implementing `std::io::Write` trait)

Open bobmoretti opened this issue 2 years ago • 3 comments

I have a use case where I'd like to write to an existing std::fs::File object.

In particular, I have used the Win32 function AllocConsole() to create a console window for my code, which runs inside of a DLL called from a GUI application. I would like to log to this console. E.g., I have the following function

fn create_console() -> windows::core::Result<File> {
    unsafe {
        Console::AllocConsole();
        let h_stdout = Console::GetStdHandle(Console::STD_OUTPUT_HANDLE)?;
        Ok(File::from_raw_handle(h_stdout.0 as *mut libc::c_void))
    }
}

I want to log to the File object returned by this function.

I see that there is a duplicate_to_stdout() method in flexi_logger, but nothing to duplicate to an arbitrary file. It looks like there's a writers module but that seems to require implementing an entire trait. Is there a straightforward way to tell flexi_logger to log to a given Write sink?

bobmoretti avatar Oct 23 '22 14:10 bobmoretti

Wrapping your file object like this would make it usable for Logger::log_to_writer:

use flexi_logger::writers::LogWriter;
use std::{
    io::{Error, ErrorKind},
    sync::{Arc, Mutex},
};

struct MyWriter<F> {
    file: Arc<Mutex<F>>,
}

impl<F: std::io::Write + Send + Sync> LogWriter for MyWriter<F> {
    fn write(
        &self,
        now: &mut flexi_logger::DeferredNow,
        record: &flexi_logger::Record,
    ) -> std::io::Result<()> {
        let mut file = self
            .file
            .lock()
            .map_err(|e| Error::new(ErrorKind::Other, e.to_string()))?;
        flexi_logger::default_format(&mut *file, now, record)
    }

    fn flush(&self) -> std::io::Result<()> {
        let mut file = self
            .file
            .lock()
            .map_err(|e| Error::new(ErrorKind::Other, e.to_string()))?;
        file.flush()
    }
}

emabee avatar Oct 23 '22 22:10 emabee

Thanks! Do you think providing this directly in flexi_logger would be useful? As in, provide a method a bit like log_to_file() but much more general?

If you think so I can take a stab at implementing it.

bobmoretti avatar Oct 25 '22 05:10 bobmoretti

If I may formulate a wish-list: it should be a reasonably documented little class of its own, like above, with some decent constructor(s), that also allows choosing the format function, in module writers. We then can link to it from Logger::log_to_writer.

emabee avatar Oct 25 '22 11:10 emabee