statsig-client 0.1.0

A Rust client library for Statsig feature flag and experimentation platform
Documentation
# statsig-client

A Rust client for Statsig's feature flag and experimentation platform. Built for production use with proper error handling, caching, and batch processing.

## Why this client?

A reliable, type-safe Rust client for Statsig designed for client-side applications. Perfect for:

- Desktop and mobile apps
- Edge functions and middleware
- Anywhere you need client-side feature flags

- Works with client keys (like the JS SDK)
- Handles network failures gracefully with retries
- Caches responses to reduce API calls and latency
- Validates inputs before they hit the wire
- Supports batch operations for better performance
- Uses builder patterns for clean, readable code

## Installation

```toml
[dependencies]
statsig-client = "0.1.0"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
```

## Getting Started

```rust
use statsig_client::{StatsigClient, User};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create the client with your Statsig client key
    let client = StatsigClient::new("your-client-key").await?;
    
    // Define your user
    let user = User::builder()
        .user_id("user-123")
        .email("user@example.com")
        .country("US")
        .build()?;
    
    // Check if a feature is enabled for this user
    if client.check_gate("new-dashboard", &user).await? {
        println!("User gets the new dashboard!");
    }
    
    Ok(())
}
```

## Configuration

Tweak the client behavior to fit your needs:

```rust
use statsig_client::{StatsigClient, StatsigClientConfig};
use std::time::Duration;

let config = StatsigClientConfig::builder()
    .api_key("your-client-key")
    .timeout(Duration::from_secs(10))           // Request timeout
    .cache_ttl(Duration::from_secs(300))        // Cache for 5 minutes
    .cache_max_capacity(1000)                   // Max cached items
    .retry_attempts(3)                          // Retry failed requests
    .retry_delay(Duration::from_millis(500))    // Delay between retries
    .build();

let client = StatsigClient::with_config(config).await?;
```

## Rich User Context

Add custom data to target your features better:

```rust
let user = User::builder()
    .user_id("user-123")
    .email("user@example.com")
    .country("US")
    .custom([
        ("subscription_plan", serde_json::json!("premium")),
        ("account_age_days", serde_json::json!(45)),
        ("last_login", serde_json::json!("2024-01-15")),
    ])
    .private_attributes([("internal_id", serde_json::json!("internal-123"))])
    .build()?;
```

## Dynamic Configs

Fetch configuration values:

```rust
let config = client.get_config("ui-settings", &user).await?;
let theme = config.get("theme").and_then(|v| v.as_str()).unwrap_or("light");
let max_items = config.get("max_items").and_then(|v| v.as_u64()).unwrap_or(10);

println!("Theme: {}, Max items: {}", theme, max_items);
```

## Event Tracking

Log user actions for analytics:

```rust
// Simple event
client.log_event("button_click", &user).await?;

// Event with metadata
use std::collections::HashMap;
let mut metadata = HashMap::new();
metadata.insert("button_id".to_string(), "submit_form".to_string());
metadata.insert("page".to_string(), "checkout".to_string());

client.log_event_with_metadata("form_submit", &user, metadata).await?;
```

## Batch Operations

Check multiple flags at once to reduce API calls:

```rust
let gates = client.check_gates(vec![
    "new-dashboard".to_string(),
    "beta-features".to_string(),
    "advanced-analytics".to_string(),
], &user).await?;

for (gate_name, enabled) in gates {
    if enabled {
        println!("{} is enabled for this user", gate_name);
    }
}
```

## Error Handling

Things go wrong. Here's how to handle it:

```rust
match client.check_gate("new-feature", &user).await {
    Ok(enabled) => println!("Feature enabled: {}", enabled),
    Err(StatsigError::Network(msg)) => {
        eprintln!("Network issue: {}. Using fallback.", msg);
        // Fall back to default behavior
    },
    Err(StatsigError::Api { status, message }) => {
        eprintln!("Statsig API error {}: {}", status, message);
        // Log the error and continue
    },
    Err(StatsigError::Validation(msg)) => {
        eprintln!("Invalid input: {}", msg);
        // Fix the input and retry
    },
    Err(e) => eprintln!("Unexpected error: {}", e),
}
```

## What Gets Cached?

The client caches responses to reduce latency and API costs:

- Feature gate results (default: 5 minutes)
- Dynamic config values (default: 5 minutes)
- Cache keys include user hash + entity name
- Automatic cache invalidation on errors

## Performance Tips

1. **Batch your checks** - Use `check_gates()` instead of multiple `check_gate()` calls
2. **Reuse the client** - Create one client and share it across your app
3. **Adjust cache TTL** - Longer TTLs reduce API calls but may delay updates
4. **Set appropriate timeouts** - Balance between reliability and responsiveness

## License

MIT OR Apache-2.0 - pick whichever works for you.

## Contributing

Found a bug or want to add something? Open an issue or send a PR.