dexcost
Rust

Quickstart

Initialize the Rust SDK and capture your first attributed LLM cost inside a Tokio async application.

Initialize dexcost, start a task, record a call, and end the task — that is all it takes to land a fully attributed cost record.

Initialize

Call dexcost::init once at application startup with a Config value, then call dexcost::close on shutdown to stop the background pusher:

use dexcost::{Config, init, close};

#[tokio::main]
async fn main() {
    init(Config {
        api_key: Some("dx_live_your_key_here".into()), // or set DEXCOST_API_KEY env var
        ..Config::default()
    }).unwrap();

    // ... rest of your application

    close();
}

init is safe to call multiple times — only the first call takes effect. Omit api_key (or leave it None) to run in local-only mode, where events are written to the on-disk SQLite buffer but not pushed to the Control Layer.

Your first tracked call

Start a task with start_task, record an LLM call, then end the task:

use dexcost::{Config, TaskOptions, TaskStatus, init, start_task, flush, close};
use rust_decimal::Decimal;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    init(Config::default())?;

    // Start a task with customer and project attribution.
    let mut task = start_task(
        "resolve_ticket",
        TaskOptions {
            customer_id: Some("acme-corp".into()),
            project_id: Some("support".into()),
            ..Default::default()
        },
    )
    .await?;

    // Record an LLM call — cost is auto-computed from bundled pricing data.
    task.record_llm_call(
        "openai",         // provider
        "gpt-4o",         // model
        1_000,            // input tokens
        500,              // output tokens
        None,             // cost_usd: None → auto-priced
        None,             // cached_tokens
        Some(250),        // latency_ms
    )
    .await?;

    // Record a non-LLM service cost with exact-precision Decimal.
    task.record_cost(
        "google_maps",
        Decimal::new(5, 3), // $0.005
        None,
        None,
    )
    .await?;

    // End the task — aggregates LLM + external costs into total_cost_usd.
    task.end(TaskStatus::Success).await?;

    println!("Total cost: {} USD", task.task().total_cost_usd);

    flush().await?;
    close();
    Ok(())
}

start_task returns a TrackedTask. record_llm_call looks up the model in the bundled pricing engine and records the computed cost; pass a non-zero cost_usd to override auto-pricing with an exact value. task.end writes the final task status and timestamps to the local buffer. flush pushes any buffered events immediately (a no-op when no API key is configured).

Run it locally

Pass environment: Some("development".into()) to Config to enable dev mode. In dev mode, every recorded event is printed to stdout and no data is sent to the cloud — useful for local development and debugging:

use dexcost::{Config, TaskOptions, TaskStatus, init, start_task, close};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    init(Config {
        environment: Some("development".into()),
        ..Config::default()
    })?;

    let mut task = start_task(
        "resolve_ticket",
        TaskOptions {
            customer_id: Some("acme-corp".into()),
            ..Default::default()
        },
    )
    .await?;

    task.record_llm_call("openai", "gpt-4o", 1_000, 500, None, None, None)
        .await?;

    task.end(TaskStatus::Success).await?;

    close();
    Ok(())
}

You can also set the DEXCOST_ENV=development environment variable instead of passing the field to Config.

Next steps

  • Instrumentation — wrapper client usage for TrackedOpenAI, TrackedAnthropic, and TrackedGemini; explicit recording with record_llm_call; retry tracking; and HTTP cost capture.
  • Configuration — all Config fields, environment variables, buffer location, flush tuning, and privacy options.

On this page