Skip to main content

Dial9HandleTokioExt

Trait Dial9HandleTokioExt 

pub trait Dial9HandleTokioExt: Sealed {
    // Required method
    fn attach_tokio_runtime(
        &self,
        builder: Builder,
        options: TokioAttachOptions,
    ) -> Result<Runtime, Error>;
}
Available on crate feature dial9 only.
Expand description

Tokio instrumentation for Dial9Handle.

Required Methods§

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 call enable_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".

Implementors§