> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/open-telemetry/opentelemetry-rust/llms.txt
> Use this file to discover all available pages before exploring further.

# Traces Overview

> Learn about distributed tracing in OpenTelemetry Rust and how to instrument your applications

The `trace` module provides types for tracking the progression of a single request while it is handled by services that make up an application. A trace is a tree of **Spans** which are objects that represent the work being done by individual services or components involved in a request as it flows through a system.

## Core Concepts

OpenTelemetry tracing consists of three main traits:

* **TracerProvider** - The entry point of the API that provides access to Tracers
* **Tracer** - Responsible for creating Spans
* **Span** - Represents a single operation within a trace

## Getting Started

Here's a basic example of instrumenting an application:

```rust theme={null}
use opentelemetry::{global, trace::Tracer, KeyValue};
use opentelemetry_sdk::trace::SdkTracerProvider;
use opentelemetry_stdout::SpanExporter;

fn init_tracer() -> SdkTracerProvider {
    let provider = SdkTracerProvider::builder()
        .with_simple_exporter(SpanExporter::default())
        .build();

    global::set_tracer_provider(provider.clone());
    provider
}

fn do_work() {
    let tracer = global::tracer("my-component");

    tracer.in_span("doing_work", |cx| {
        // Your application logic here
        println!("Work is being traced!");
    });
}

fn main() {
    let provider = init_tracer();
    do_work();
    provider.shutdown().unwrap();
}
```

## Trace Structure

A trace is a tree of spans. Each trace contains:

* A **root span** - The top-level span with no parent
* Zero or more **child spans** - Spans that have a parent span

Spans can be nested to form a trace tree:

```rust theme={null}
let tracer = global::tracer("my-tracer");

tracer.in_span("parent_operation", |_cx| {
    // This is the root span

    tracer.in_span("child_operation", |_cx| {
        // This is a child span
    });
});
```

## Synchronous vs Asynchronous Code

### Synchronous Code

In synchronous code, use `in_span` for automatic span management:

```rust theme={null}
use opentelemetry::{global, trace::Tracer};

let tracer = global::tracer("my-component");

tracer.in_span("operation", |_cx| {
    // Span is active here
    // Span ends automatically when closure returns
});
```

### Asynchronous Code

For async code, use the `FutureExt` trait to attach context to futures:

```rust theme={null}
use opentelemetry::{trace::FutureExt, Context};

let cx = Context::current();

let my_future = async {
    // Async work here
};

my_future.with_context(cx).await;
```

<Warning>
  Do not use `mark_span_as_active` directly in async blocks, as the guard will remain active for the entire lifetime of the future, not just when it's being polled.
</Warning>

## Working with the Global TracerProvider

OpenTelemetry provides a global `TracerProvider` singleton:

```rust theme={null}
use opentelemetry::global;

// Get a tracer anywhere in your application
let tracer = global::tracer("my-component");

// Or with version information
let tracer = global::tracer_with_version(
    "my-component",
    env!("CARGO_PKG_VERSION")
);
```

## Complete Example with OTLP

Here's a complete example using the OTLP exporter:

```rust theme={null}
use opentelemetry::{global, trace::{Tracer, TraceContextExt}, KeyValue};
use opentelemetry_otlp::SpanExporter;
use opentelemetry_sdk::trace::SdkTracerProvider;
use opentelemetry_sdk::Resource;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let exporter = SpanExporter::builder()
        .with_tonic()
        .build()?;

    let provider = SdkTracerProvider::builder()
        .with_resource(Resource::builder()
            .with_service_name("my-service")
            .build())
        .with_batch_exporter(exporter)
        .build();

    global::set_tracer_provider(provider.clone());

    let tracer = global::tracer("my-component");

    tracer.in_span("main_operation", |cx| {
        let span = cx.span();
        span.add_event(
            "Processing started",
            vec![KeyValue::new("items", 100)]
        );
        span.set_attribute(KeyValue::new("user.id", "12345"));

        // Your application logic
    });

    provider.shutdown()?;
    Ok(())
}
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Tracers" icon="diagram-project" href="/traces/tracers">
    Learn how to create and configure tracers
  </Card>

  <Card title="Spans" icon="cube" href="/traces/spans">
    Understand span lifecycle, attributes, and events
  </Card>

  <Card title="Context Propagation" icon="arrow-right-arrow-left" href="/traces/context">
    Propagate trace context across service boundaries
  </Card>

  <Card title="Sampling" icon="filter" href="/traces/sampling">
    Control which traces are recorded and exported
  </Card>
</CardGroup>
