> ## Documentation Index
> Fetch the complete documentation index at: https://docs.squasher.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Rust

> Send errors and logs from Rust applications to Squasher.

For native Rust error capture, panic hooks, tags, users, breadcrumbs, and flush helpers, start with the [Rust SDK](/sdks/rust). Use this OpenTelemetry guide when your Rust service already emits traces and logs through `tracing`.

## Recommended: OpenTelemetry SDK

Use the official Rust OTel SDK with the `tracing` crate for structured error reporting.

### 1. Install

```toml theme={null}
# Cargo.toml
[dependencies]
opentelemetry = "0.27"
opentelemetry_sdk = { version = "0.27", features = ["rt-tokio"] }
opentelemetry-otlp = { version = "0.27", features = ["http-proto"] }
tracing = "0.1"
tracing-subscriber = "0.3"
tracing-opentelemetry = "0.28"
```

## Agent handoff

```text theme={null}
For a Rust service, prefer the native Squasher Rust SDK for basic error capture. Use this OpenTelemetry setup only when the app already uses tracing spans or needs vendor-neutral OTLP export. Keep SQUASHER_API_KEY in environment variables and verify with one error event.
```

### 2. Configure

```rust theme={null}
use opentelemetry::trace::TracerProvider;
use opentelemetry_otlp::WithExportConfig;
use opentelemetry_sdk::resource::{
    EnvResourceDetector, SdkProvidedResourceDetector, ResourceDetector,
};
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};

fn init_telemetry() {
    let exporter = opentelemetry_otlp::SpanExporter::builder()
        .with_http()
        .with_endpoint("https://ingest.squasher.ai")
        .with_headers(std::collections::HashMap::from([(
            "x-squasher-key".into(),
            "sq_pk_your_api_key".into(),
        )]))
        .build()
        .expect("failed to create exporter");

    let provider = opentelemetry_sdk::trace::TracerProvider::builder()
        .with_batch_exporter(exporter)
        .build();

    let tracer = provider.tracer("my-rust-service");
    let otel_layer = tracing_opentelemetry::layer().with_tracer(tracer);

    tracing_subscriber::registry()
        .with(otel_layer)
        .with(tracing_subscriber::fmt::layer())
        .init();
}
```

### 3. Use

```rust theme={null}
use tracing::{error, info, instrument};

#[instrument]
async fn process_order(order_id: &str) -> Result<(), Box<dyn std::error::Error>> {
    info!(order_id, "Processing order");

    let result = db_query(order_id).await;
    if let Err(ref e) = result {
        error!(error = %e, order_id, "Order processing failed");
    }
    result
}
```

## Alternative: Direct HTTP API

```rust theme={null}
use reqwest::Client;
use serde_json::json;

pub struct Squasher {
    client: Client,
    endpoint: String,
    api_key: String,
}

impl Squasher {
    pub fn new(project_id: &str, api_key: &str) -> Self {
        Self {
            client: Client::new(),
            endpoint: format!("https://ingest.squasher.ai/v1/ingest/{project_id}"),
            api_key: api_key.to_string(),
        }
    }

    pub async fn capture_error(&self, error: &dyn std::error::Error, tags: serde_json::Value) {
        let _ = self.client
            .post(&self.endpoint)
            .header("Content-Type", "application/json")
            .header("x-squasher-key", &self.api_key)
            .json(&json!({
                "message": error.to_string(),
                "type": std::any::type_name_of_val(error),
                "level": "error",
                "tags": tags,
            }))
            .send()
            .await;
    }
}
```
