slog-rs / async

Asynchronous drain for slog-rs v2
Apache License 2.0
28 stars 24 forks source link

question: How to flush on a async logger? #35

Open gabyx opened 8 months ago

gabyx commented 8 months ago

How can I instruct the log = create_logger_cli(false) to be flushed manually (I have a password prompt on stdout which should first flush the whole log such that the prompt is at the right place) Basically log.flush() which would block until all records have been processed by the thread? Is there another better method?

pub fn create_logger_cli(timestamp: bool) -> Arc<Logger> {
    let decorator = slog_term::TermDecorator::new().build();

    let mut d1 = slog_term::FullFormat::new(decorator);

    if !timestamp {
        d1 = d1.use_custom_timestamp(no_out);
    }

    let drain = d1.build().fuse();

    let drain = slog_async::Async::new(drain)
        .chan_size(5_000_000)
        .build()
        .fuse();

    return Arc::new(slog::Logger::root(drain, o!()));
}
dpc commented 8 months ago

Can't really flush an async logger, as it can't not control the receiver on the other side of a channel.

The closest thing we could have is maybe waiting for the channel to empty. But I'm not sure if we should.

Generally displaying password prompts via logging is not a good idea. One should be using stderr for that, or some completely different things altogether.

gabyx commented 8 months ago

Jeah sure. I guessed that its kind of tricky, waiting till the channel has emptied is close, but probably still no guaranteed that the underlaying drains have been flushed... only the channel is empty...

Thanks for the response. I find another solution.

dpc commented 8 months ago

Ah. I'm silly. You are logging with slog-async, and then you might want to display prompt etc. on stderr . It seems like a legitimate use case...

Under the hood we are using https://github.com/slog-rs/async/blob/c2040ac96ddd189bb382e45bec9cb28338e5348c/lib.rs#L336 to send messages, from crossbeam-channel.

It does support is_empty(): https://docs.rs/crossbeam-channel/latest/crossbeam_channel/struct.Sender.html#method.is_empty

So i guess we (I mean... you, if you care enough to submit a PR :D ) could add a new method to the trait / API that would attempt to "flush" (e.g. wait until is_empty() == true with some polling interval). If it's a trait, add a default impl that just return a custom IO error "unsupported" for backward compat.

@Techcable for awareness.

gabyx commented 8 months ago

Yes, you understood that correctly. Yes, sounds interesting to have a look at over the weekend. Thanks for pointing into the directions! If there are more thoughts let me know.

gabyx commented 8 months ago

@dpc: Some question for undestanding the problem better: Do you think it makes sense to make a new trait Flushable which a Drain instance can have where it would implement flush in lib slog/lib.rs. And then make an implementation for Async as you suggested =).

Thanks alot

gabyx commented 8 months ago

Ah maybe its better to add this functionality to the Drain with a default implementation?

dpc commented 8 months ago

Most ecosystem expects Drain already, so it would have be a new method on an existing trait with an default impl that does something reasonable (like signals lack of support for flushing).