# tokio task spawn metadata
So far, this is collecting the various strategies for including metadata, such as for `tracing`, when spawning a new task in Tokio.
## status-quo
### `future.instrument()`
A user can currently manually create a tracing `Span`, and instrument any future before calling `tokio::spawn`. Something like:
```rust
let span = tracing::debug_span("yolo");
let future = async {
yeet().await;
};
tokio::spawn(future.instrument(span));
```
- **Pros**:
- already works just fine
- very flexible if you want to add many fields to the span
- **Cons**:
- kind of onorous if all you want is a name for the task
- definitely not obvious
### `--cfg tokio_unstable`
This is an _unstable_ Tokio feature, which will automatically make a span for all tasks that go through `spawn`. Introduced in [this PR](https://github.com/tokio-rs/tokio/pull/2655).
- **Pros**:
- Automatically includes useful data without the user having to figure it out
- `spawn`, `spawn_local`, `spawn_blocking`
- The `std::any::type_name()` of the future
- With `#[track_caller]`, could include the file, line, and function name of exactly _where_ the task was spawned from.
- **Cons**:
- It's unstable.
- It doesn't allow customizing the span at all.
Part the instability of this feature is that Tokio can't be emitting `tracing` spans that people depend on, while `tracing` is pre-1.0, because if Tokio upgrades to `tracing` 1.0, those people would suddenly no longer receive the emitted spans. It seems likely that to support the suggestions below, we'd at the very least need to have reaching `tracing` 1.0. Or, the alternative would be to mark the proposed APIs as _also_ unstable.
## `task::Builder`
This would be a parallel type to `std::thread::Builder`.
```rust
pub struct Builder {
id: TaskId, // unique id, similar to ThreadId
// ..
}
```
- **Pros**:
- Is a natural way to specific a "name", since it mimics `std::thread`.
- Provides a place to add any other "meta" stuff to a task.
- There's `stack_size` for threads, not sure that particularly works for `task`s, but maybe there's other things to configure
- Priority?
- "CPU affinity"?
- **Cons**:
- One downside is that it's possible to combine using the builder for metadata, *and* `future.instrument`. Maybe that's not a big deal :shrug:
### `Builder.name`
The `std::thread` builder has the ability to set the thread name. We could allow setting the "task name", which could be used to create the tracing `span`.
One difference is that the "thread name" can be a `String`, and so can be dynamically created. The "span name" requires a `&' static str`.
### `Builder.span`?
If we wanted to expose `tracing-core`, we could allow allow configuring a span outside the builder, and then just passing it directly. However, it's not clear how this is much better than just `future.instrument(span)`.
### `Builder.local`?
If we have a builder, we _could_ consider allowing configuring of "task locals" directly on the builder. This is a question mark, could be considered later.
### `Builder.tag`?
This is basically `Span::record(field, value)`. We could either expose the traits directly (`valuable`?), or define custom traits (which can get hairy).
I picked the method name `tag` since `record` didn't seem to make as much sense for a `task::Builder`. The name `tag` is used in other languages/libraries to store arbitrary opaque data.
## `spawn!` macro
Initially [proposed](https://github.com/tokio-rs/tokio/issues/1180) with for two purposes:
- Return a `JoinHandle`
- Allow decorating a task with `tracing` metadata.
Tokio 1.0 already returns `JoinHandle`s by default, and thus the issue was closed. However, the idea is at least worth considering, even if we decide against it.
```rust
let task = tokio::spawn!(async {
toge().await
}, "we_are", stronger=&together);
```
This could expand either to just `tokio::spawn(future.instrument(tracing::span!(..)))`, or to using the proposed `task::Builder`.
- **Pros**:
- Convenient way to combine spawning and tracing fields.
- Perhaps easier to include `file!()`, `line!()`, and `function!()` automatically.
- However, with `#[track_caller]`, we could perhaps get this stuff automatically on `Builder::new()`.
- **Cons**:
- Some people don't like macros, since they can seem magical.
- It becomes _yet another_ way to do the same thing.
- But then again, macros usually are doing a thing that's already possible, just making it more convenient.