Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
bobmoretti opened this issue Oct 23, 2022 · 3 comments
Open

Comments

@bobmoretti
Copy link

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?

@emabee
Copy link
Owner

emabee commented Oct 23, 2022

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()
    }
}

@bobmoretti
Copy link
Author

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.

@emabee
Copy link
Owner

emabee commented Oct 25, 2022

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants