-
Couldn't load subscription status.
- Fork 97
Description
In our internal framework we have some relatively expensive log fields to compute (formatting is expensive):
"http.host" => format!("{:?}", extract_host(req))
We also have approximately zero logging in a course of normal request processing in the heaviest users, so all of this effort goes to waste. We can do this and switch to lazy evaluation:
"http.host" => PushFnValue(move |_, s| s.emit(format_args!("{host:?}")))
This is better, but it has an unfortunate downside for framework consumers that do log more than once during request processing.
We could get the best of both worlds by making evaluation both lazy (above) and cached (sketched by @TheJokr):
pub struct LazyValue<T, F>(LazyLock<T, F>);
impl<T: slog::Value, F: FnOnce() -> T> slog::Value for LazyValue<T, F> {
fn serialize(&self, ...) -> ... {
(*self.0).serialize(...)
}
}
impl<T, F: FnOnce() -> T> LazyValue<T, F> {
pub const fn new(init_fn: F) -> Self {
Self(LazyLock::new(init_fn))
}
}It seems generally useful, so I think this should live in slog itself, as something like PushFnValueCached perhaps.