liveBook · Manning

Instrumentation

As explained in Code Like a Pro in Rust

tracing is a Rust library for instrumenting programs and emitting structured diagnostic telemetry.

Instrumentation measures performance and exposes diagnostic telemetry from Rust applications. The tracing crate emits structured traces as logs or through OpenTelemetry, while Tokio integrations support live analysis of asynchronous programs. section 8.9

Apply instrumentation with a focused production workflow:

  • Configure a subscriber to receive traces before expecting useful output. section 8.9
  • Mark functions with #[tracing::instrument] at the points whose execution, latency, or task behavior matters. section 8.9
  • Select useful levels and targets instead of enabling every message by default. section 9.5.2
  • Use logs or OpenTelemetry for persistent observability; reserve tokio-console for interactive debugging. section 8.9
use tokio::time::{sleep, Duration};
 
#[tracing::instrument]                    #1
async fn sleep_1s() {
    sleep(Duration::from_secs(1)).await;
}
 
#[tracing::instrument]
async fn sleep_2s() {
    sleep(Duration::from_secs(2)).await;
}
 
#[tracing::instrument]
async fn sleep_3s() {
    sleep(Duration::from_secs(3)).await;
}
 
#[tokio::main]
async fn main() {
    console_subscriber::init();           #2
 
    loop {
        tokio::spawn(sleep_1s());         #3
        tokio::spawn(sleep_2s());
        sleep_3s().await;                 #4
    }
}

This runnable pattern instruments three asynchronous sleep functions, initializes the console subscriber, and mixes spawned tasks with an awaited task for live inspection. section 8.9

Listing 9.3 API service init_tracing() function in src/main.rs
fn init_tracing() {
    use tracing_subscriber::{
        filter::LevelFilter, fmt, prelude::*, EnvFilter
    };
 
    let rust_log = std::env::var(EnvFilter::DEFAULT_ENV)                   #1
        .unwrap_or_else(|_| "sqlx=info,tower_http=debug,info".to_string());
 
    tracing_subscriber::registry()                                         #2
        .with(fmt::layer())                                                #3
        .with(
            EnvFilter::builder()                                           #4
                .with_default_directive(LevelFilter::INFO.into())
                .parse_lossy(rust_log),
        )
        .init();
}

This initialization pattern reads RUST_LOG, supplies defaults, attaches formatted output, applies EnvFilter directives, and installs the subscriber. section 9.5.2

Avoid setting RUST_LOG=trace casually: unrestricted output can become noisy and is discouraged in production when unnecessary. Prefer explicit crate-level directives such as sqlx=info and tower_http=debug. section 9.5.2

How Code Like a Pro in Rust covers it

How deep it goes
Explains subscribers, function instrumentation, filtering, and console setup, but does not detail tracing internals.
Examples
Demonstrates instrumented sleep tasks, tokio-console views, and an API service initializer using RUST_LOG and EnvFilter.
What you can do after
Diagnose async behavior with tokio-console and configure persistent trace output through logs or OpenTelemetry.
How it connects
Connects tracing with Tokio, OpenTelemetry, tokio-console, tracing subscribers, and EnvFilter.

Also explained in

Compare how 13 books explain instrumentation →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Code Like a Pro in Rust. The section links point to the parts of the book it draws on.