tokio-rs / tracing

Application level tracing for Rust.
https://tracing.rs
MIT License
5.14k stars 671 forks source link

Cannot write custom `Layer` that uses `Format` #2988

Open jsimonrichard opened 1 month ago

jsimonrichard commented 1 month ago

Feature Request

I'm new to this crate, to apologies if I'm missing something obvious. But here goes...

I want to create a custom Layer that uses the standard tracing_subscriber::fmt::format::Format formatter.

My plan was to implement Layer::on_event, which is provided a Context. To use the formatter, it seems like I need a FmtContext. However, I can't figure out how to create one of those from a Context. In fact, I haven't found any public functions that return FmtContext.

Crates

tracing-subscriber

Motivation

My particular use case is that I want to send backend logs to the fronted (like in tauri_plugin_log). Each time something is logged I need to call a custom function (which takes a string message input, among other things), but I don't want to write custom formatting for that string.

Proposal

In tracing_subscriber::fmt::Layer, the private make_ctx function is used:

impl<S, N, E, W> Layer<S, N, E, W>
where
    S: Subscriber + for<'a> LookupSpan<'a>,
    N: for<'writer> FormatFields<'writer> + 'static,
    E: FormatEvent<S, N> + 'static,
    W: for<'writer> MakeWriter<'writer> + 'static,
{
    #[inline]
    fn make_ctx<'a>(&'a self, ctx: Context<'a, S>, event: &'a Event<'a>) -> FmtContext<'a, S, N> {
        FmtContext {
            ctx,
            fmt_fields: &self.fmt_fields,
            event,
        }
    }
}

I would like to create a similar function that creates a FmtContext. Maybe something like this:

impl<a, S> Context<'a, S> {
    pub fn to_fmt_context<N>(self, fmt_fields: ?, event: &'a Event<'a>) -> FmtContext<'a, S, N> {
        FmtContext {
            self,
            fmt_fields,
            event
        }
    }
}

Alternatives

I'm not sure. Maybe this could be a function on FmtContext? But I think making this a function on Context makes it clear that this is a conversion from Context to FmtContext which requires extra parameters (fmt_fields and events).

LHolten commented 3 days ago

I would also really like this, my use case is turning some errors into panics during tests.

kaffarell commented 1 day ago

Hmm AFAIK this is currently not possible. One workaround would be to use MakeWriter and implement io::Write. https://docs.rs/tracing-subscriber/latest/tracing_subscriber/fmt/struct.Layer.html#method.with_writer