2 releases

0.1.1 May 31, 2019
0.1.0 May 31, 2019
Download history 164/week @ 2020-11-04 149/week @ 2020-11-11 122/week @ 2020-11-18 106/week @ 2020-11-25 94/week @ 2020-12-02 106/week @ 2020-12-09 654/week @ 2020-12-16 130/week @ 2020-12-23 145/week @ 2020-12-30 249/week @ 2021-01-06 311/week @ 2021-01-13 163/week @ 2021-01-20 196/week @ 2021-01-27 133/week @ 2021-02-03 73/week @ 2021-02-10 165/week @ 2021-02-17

312 downloads per month
Used in logsley

MIT/Apache

8KB

Slog Scope for Futures

version documentation license

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.


lib.rs:

Slog Scopes for the Async World

This crate provides a mechanism to use slog scopes with Futures.

The Problem

With synchronous code, slog-scope works as expected. But what about when dealing with async/await?

This won't compile:

slog_scope::scope(&logger, || {
    some_operation().await // Error: can't use await outside of an async fn/block
})

This compiles, but doesn't do what you actually want:

# #![feature(async_await)]
# async fn some_operation() {}
# async {
# use slog::o;
let logger = slog_scope::logger().new(o!("name" => "sub logger"));

let fut = slog_scope::scope(&logger, async || { // <- scope start
    some_operation().await
}); // <- scope end

fut.await // Scope not active here while the future is actually running
# };

The Solution

Rather than using a closure to represent a slog scope, the logger must instead be tied to the future itself, and its poll method wrapped in a scope. The SlogScope type provides a Future wrapper that does exactly that.

Usage

Using the wrapper directly:

# #![feature(async_await)]
# async fn some_operation() {}
# async {
# use slog::o;
use slog_scope_futures::SlogScope;

let logger = slog_scope::logger().new(o!("name" => "sub logger"));

SlogScope::new(logger, some_operation()).await
# };

Using the convenience trait:

# #![feature(async_await)]
# async fn some_operation() {}
# async {
# use slog::o;
use slog_scope_futures::FutureExt;

let logger = slog_scope::logger().new(o!("name" => "sub logger"));

some_operation().with_logger(logger).await
# };

Borrowed vs Owned Loggers

Often, you need a Future to be 'static so that it can be spawned into an executor. Other times, though, you can get away with borrowing the logger. This way, it can be re-used without additional cloning of the handle.

Because the SlogScope wrapper takes any L: Borrow<Logger>, you can create it with either an owned or a borrowed Logger.

# #![feature(async_await)]
# async fn some_operation() {}
# async fn some_other_operation() {}
# async {
# use slog::o;
# use core::future::Future;
use slog_scope_futures::FutureExt;

let logger = slog_scope::logger().new(o!("name" => "sub logger"));

some_operation().with_logger(&logger).await; // <- borrowed logger
let fut = some_other_operation().with_logger(logger); // <- owned logger

async fn assert_static<F: Future + 'static>(f: F) -> F::Output { f.await }

assert_static(fut).await
# };

Dependencies

~330KB