Is there a way to make the `log` crate macros blocking?

I have a situation where I need to make sure that every call to log::info! and the other logging macros blocks until the logs are flushed. I know that this is in general contrary to what you would want and less performant, but it is required for the environment I'm in. I need to know that the log::info! call waits until the log is actually written before it continues.

Is there any way to make the log macro calls block until the log is flushed? I feel like this is probably outside of the intent of the log crate and that I will need to implement something similar myself.

I'm using a custom logging implementation that uses a CLI to log messages to a program on the system.

This depends on the specific logger implementation. (There are several.) If you are already committed to a specific implementation, let us know, and maybe someone will have better advice. But for starters you could create a special purpose logger that writes and flushes stdout. Something like this, maybe:

use log::{Record, Level, Metadata};
use std::io;

struct SimpleLogger;

impl log::Log for SimpleLogger {
    fn enabled(&self, metadata: &Metadata) -> bool {
        metadata.level() <= Level::Info
    }

    fn log(&self, record: &Record) {
        if self.enabled(record.metadata()) {
            let stdout = io::stdout();
            let mut handle = stdout.lock();

            write!(handle, "{} - {}", record.level(), record.args()).unwrap();
            handle.flush().unwrap();
        }
    }

    fn flush(&self) {}
}

(Adapted from the example implementation in the log crate docs.)

1 Like

OK, yeah, I just realized that I'm already doing that. I didn't realize that the log macro was calling my loggers log function immediately and blocking until it was done, but that makes sense and explains the separate flush() method.

I was confused because I was seeing some strange behavior with the logs output by the CLI I was calling to do the logging itself: logs would come late or not show up at all sometimes. That behavior must be caused by the implementation of the CLI I'm using to log or my failure to call that CLI from my logger's log function. I'll have to investigate further into that to see where the problem lies.

Anyway, thanks!

:man_facepalming: I found my problem. In the function that I used to call the logging CLI I used Command::spawn which is non-blocking.

I must have been doing that intentionally for performance before I realized that it wasn't going to work right for my use case. Now it's working great! :smiley:

3 Likes