Trait Dial9HandleTokioExt
pub trait Dial9HandleTokioExt: Sealed {
// Required method
fn attach_tokio_runtime(
&self,
builder: Builder,
options: TokioAttachOptions,
) -> Result<Runtime, Error>;
}dial9 only.Expand description
Tokio instrumentation for Dial9Handle.
Required Methods§
fn attach_tokio_runtime(
&self,
builder: Builder,
options: TokioAttachOptions,
) -> Result<Runtime, Error>
fn attach_tokio_runtime( &self, builder: Builder, options: TokioAttachOptions, ) -> Result<Runtime, Error>
Instrument a builder you configured, build it, and return the runtime.
Get a handle from Recorder::handle,
or clone one per thread. Each call attaches another runtime (it does not
replace earlier ones) and every runtime attached to the same recorder
records into the same trace.
builder: yours to configure. dial9 does not seed it, so callenable_all(or the drivers you need) yourself, and pick the flavor. Taken by value: the hooks installed on it belong to this one runtime.options: dial9 tracing behavior for this runtime (runtime name, task tracking, task-dump config, composed hooks).
On a disabled recorder this still returns a working, untraced runtime, as
does tokio_instrumentation_enabled(false), which skips instrumentation
for this runtime only.
Do not set builder thread/task callbacks directly (on_thread_start and
friends) because dial9 installs its own and would overwrite yours. Pass
TokioHooks in the options to compose them instead.
Drop the runtime before calling
Recorder::graceful_shutdown
on the recorder this handle came from, so the runtime’s workers flush.
Attach claims the calling thread: the handle is installed
thread-locally, so Dial9Handle::current and dial9::spawn work
there before the first poll, replacing any handle a previous attach
installed. Attach a current_thread runtime on the thread that will
drive it.
Attaching is permanent: contexts and metrics of attached runtimes stay registered for the recorder’s life, even after the runtime drops.
§Errors
Fails if Tokio cannot build the runtime, or if the recorder has already shut down.
Drive the root future with block_on, not
Runtime::block_on: to ensure polls and wakes
are captured.
use dial9_core::buffer::MemoryBuffer;
use dial9_core::recorder::recorder;
use dial9_tokio_telemetry::telemetry::{Dial9HandleTokioExt, TokioAttachOptions};
let recorder = recorder(MemoryBuffer::new(1 << 20)?).build();
let mut builder = tokio::runtime::Builder::new_multi_thread();
builder.enable_all().worker_threads(4);
let runtime = recorder
.handle()
.attach_tokio_runtime(builder, TokioAttachOptions::default())?;The handle is cheap to clone, so several threads can each attach their own runtime off the same recorder:
use dial9_core::buffer::MemoryBuffer;
use dial9_core::recorder::recorder;
use dial9_tokio_telemetry::telemetry::{Dial9HandleTokioExt, TokioAttachOptions};
let recorder = recorder(MemoryBuffer::new(1 << 20)?).build();
let handle = recorder.handle().clone();
let threads: Vec<_> = (0..2)
.map(|_| {
let handle = handle.clone();
std::thread::spawn(move || {
let mut builder = tokio::runtime::Builder::new_current_thread();
builder.enable_all();
let runtime = handle
.attach_tokio_runtime(builder, TokioAttachOptions::default())
.expect("build runtime");
dial9_tokio_telemetry::block_on(&runtime, async { /* ... */ });
})
})
.collect();Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".