> ## 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.

# Basic Tracing

> Learn how to create and export traces using OpenTelemetry Rust SDK with complete working examples

## Overview

Tracing allows you to track the flow of requests through your application. This guide shows you how to set up basic tracing with the OpenTelemetry Rust SDK using the stdout exporter.

## Dependencies

Add these dependencies to your `Cargo.toml`:

```toml Cargo.toml theme={null}
[dependencies]
opentelemetry = { version = "*", features = ["trace"] }
opentelemetry_sdk = { version = "*", features = ["trace", "rt-tokio"] }
opentelemetry-stdout = { version = "*", features = ["trace"] }
tokio = { version = "1", features = ["full"] }
```

## Complete Example

<Steps>
  <Step title="Initialize the Tracer Provider">
    Set up the tracer provider with a stdout exporter and configure the trace context propagator.

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

    fn init_tracer() -> SdkTracerProvider {
        global::set_text_map_propagator(TraceContextPropagator::new());
        
        // Install stdout exporter pipeline to be able to retrieve the collected spans.
        let provider = SdkTracerProvider::builder()
            .with_simple_exporter(SpanExporter::default())
            .build();

        global::set_tracer_provider(provider.clone());
        provider
    }
    ```
  </Step>

  <Step title="Create and Start Spans">
    Create spans to track operations in your application.

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

    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let tracer_provider = init_tracer();
        let tracer = global::tracer("example/client");
        
        // Create a span with SpanKind::Client
        let span = tracer
            .span_builder("my_operation")
            .with_kind(SpanKind::Client)
            .start(&tracer);
        
        // Your application logic here
        
        // Shutdown the provider to flush all spans
        tracer_provider.shutdown()?;
        Ok(())
    }
    ```
  </Step>

  <Step title="Add Span Attributes">
    Enrich your spans with additional context using attributes.

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

    let mut span = tracer
        .span_builder("database_query")
        .with_kind(SpanKind::Internal)
        .with_attributes([
            KeyValue::new("db.system", "postgresql"),
            KeyValue::new("db.operation", "SELECT"),
        ])
        .start(&tracer);

    // Add events to spans
    span.add_event("Processing started", vec![]);
    ```
  </Step>

  <Step title="Parent-Child Span Relationships">
    Create nested spans to represent hierarchical operations.

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

    // Create parent span
    let parent_span = tracer
        .span_builder("parent_operation")
        .with_kind(SpanKind::Server)
        .start(&tracer);

    let parent_cx = Context::current_with_span(parent_span);

    // Create child span with parent context
    let child_span = tracer
        .span_builder("child_operation")
        .with_kind(SpanKind::Internal)
        .start_with_context(&tracer, &parent_cx);
    ```
  </Step>
</Steps>

## Span Kinds

OpenTelemetry defines different span kinds to categorize operations:

* **`SpanKind::Client`** - Represents a request to a remote service
* **`SpanKind::Server`** - Represents handling an incoming request
* **`SpanKind::Internal`** - Represents an internal operation
* **`SpanKind::Producer`** - Represents a message producer
* **`SpanKind::Consumer`** - Represents a message consumer

<Note>
  Always call `shutdown()` on the tracer provider before your application exits to ensure all spans are properly flushed to the exporter.
</Note>

## Output

When you run your application, the stdout exporter will print span data in JSON format to the console, showing:

* Trace ID and Span ID
* Span name and kind
* Start and end timestamps
* Attributes and events
* Parent-child relationships

<Tip>
  For production use, replace the stdout exporter with an OTLP exporter to send traces to a backend like Jaeger, Zipkin, or a cloud observability platform. See the [OTLP HTTP](/examples/otlp-http) and [OTLP gRPC](/examples/otlp-grpc) examples.
</Tip>
