# IronTelemetry SDK for Rust Error monitoring and crash reporting SDK for Rust applications. Capture exceptions, track user journeys, and get insights to fix issues faster. [![Crates.io](https://img.shields.io/crates/v/irontelemetry.svg)](https://crates.io/crates/irontelemetry) [![Documentation](https://docs.rs/irontelemetry/badge.svg)](https://docs.rs/irontelemetry) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) ## Installation Add this to your `Cargo.toml`: ```toml [dependencies] irontelemetry = "0.1" ``` For async support: ```toml [dependencies] irontelemetry = { version = "0.1", features = ["async"] } ``` ## Quick Start ### Basic Exception Capture ```rust use irontelemetry::{Client, SeverityLevel}; fn main() -> Result<(), Box> { // Initialize with your DSN let client = Client::new("https://pk_live_xxx@irontelemetry.com")?; // Capture a message client.capture_message("Application started", SeverityLevel::Info); // Capture an exception client.capture_exception("RuntimeError", "Something went wrong"); // Capture from a std::error::Error if let Err(e) = do_something() { client.capture_error(&*e); } Ok(()) } ``` ### Journey Tracking Track user journeys to understand the context of errors: ```rust use irontelemetry::{Client, BreadcrumbCategory, create_journey_manager}; fn main() -> Result<(), Box> { let client = Client::new("https://pk_live_xxx@irontelemetry.com")?; let journey_manager = create_journey_manager(&client); // Start a journey let mut journey = journey_manager.start_journey("Checkout Flow"); journey.set_user("user-123", Some("user@example.com"), Some("John Doe")); // Track steps with automatic error handling let result = journey.run_step("Validate Cart", BreadcrumbCategory::Business, || { validate_cart() }); if let Err(e) = result { journey.fail(Some(&e.to_string())); client.capture_exception("ValidationError", &e.to_string()); return Err(e.into()); } let result = journey.run_step("Process Payment", BreadcrumbCategory::Business, || { process_payment() }); if let Err(e) = result { journey.fail(Some(&e.to_string())); client.capture_exception("PaymentError", &e.to_string()); return Err(e.into()); } journey.complete(); Ok(()) } ``` Or track steps manually: ```rust let mut journey = journey_manager.start_journey("Checkout Flow"); let mut step = journey.start_step("Validate Cart", BreadcrumbCategory::Business); step.set_data("cart_items", json!(5)); match validate_cart() { Ok(_) => step.complete(), Err(e) => { step.fail(Some(&e.to_string())); journey.fail(Some(&e.to_string())); return Err(e.into()); } } journey.complete(); ``` ## Configuration ```rust use irontelemetry::{Client, TelemetryOptions}; let options = TelemetryOptions::new("https://pk_live_xxx@irontelemetry.com") .environment("production") .app_version("1.2.3") .sample_rate(1.0) // 100% of events .debug(false) .before_send(|event| { // Filter or modify events if event.message.as_ref().map(|m| m.contains("expected")).unwrap_or(false) { return None; // Drop the event } Some(event) }); let client = Client::with_options(options)?; ``` ### Configuration Options | Option | Type | Default | Description | |--------|------|---------|-------------| | `dsn` | String | required | Your Data Source Name | | `environment` | String | "production" | Environment name | | `app_version` | String | "0.0.0" | Application version | | `sample_rate` | f64 | 1.0 | Sample rate (0.0 to 1.0) | | `max_breadcrumbs` | usize | 100 | Max breadcrumbs to keep | | `debug` | bool | false | Enable debug logging | | `before_send` | Fn | None | Hook to filter/modify events | | `enable_offline_queue` | bool | true | Enable offline queue | | `max_offline_queue_size` | usize | 500 | Max offline queue size | ## Features - **Automatic Stack Traces**: Full stack traces captured with exceptions - **Journey Tracking**: Track user flows and correlate errors with context - **Breadcrumbs**: Leave a trail of events leading up to an error - **User Context**: Associate errors with specific users - **Tags & Extras**: Add custom metadata to your events - **Thread-Safe**: All operations are safe for concurrent use with `Arc` and `RwLock` - **Zero-Copy Where Possible**: Efficient memory usage with borrowed data ## Breadcrumbs ```rust use irontelemetry::{BreadcrumbCategory, SeverityLevel}; use std::collections::HashMap; use serde_json::json; // Add simple breadcrumbs client.add_breadcrumb("User clicked checkout button", BreadcrumbCategory::Ui); client.add_breadcrumb("Payment API called", BreadcrumbCategory::Http); // With level client.add_breadcrumb_with_level( "User logged in", BreadcrumbCategory::Auth, SeverityLevel::Info, ); // With data let mut data = HashMap::new(); data.insert("url".to_string(), json!("/api/checkout")); data.insert("statusCode".to_string(), json!(200)); data.insert("duration".to_string(), json!(150)); client.add_breadcrumb_with_data( "API request completed", BreadcrumbCategory::Http, SeverityLevel::Info, data, ); ``` ### Breadcrumb Categories ```rust BreadcrumbCategory::Ui // User interface interactions BreadcrumbCategory::Http // HTTP requests BreadcrumbCategory::Navigation // Page/route navigation BreadcrumbCategory::Console // Console output BreadcrumbCategory::Auth // Authentication events BreadcrumbCategory::Business // Business logic events BreadcrumbCategory::Notification // Notification events BreadcrumbCategory::Custom // Custom events ``` ## Severity Levels ```rust SeverityLevel::Debug SeverityLevel::Info SeverityLevel::Warning SeverityLevel::Error SeverityLevel::Fatal ``` ## User Context ```rust use irontelemetry::User; use serde_json::json; use std::collections::HashMap; // Simple user ID client.set_user_by_id("user-123"); // With email client.set_user_with_email("user-123", "user@example.com"); // Full user object let mut data = HashMap::new(); data.insert("plan".to_string(), json!("premium")); client.set_user(User::new("user-123") .with_email("user@example.com") .with_name("John Doe") .with_data(data)); ``` ## Tags and Extra Data ```rust use serde_json::json; use std::collections::HashMap; // Set individual tags client.set_tag("release", "v1.2.3"); client.set_tag("server", "prod-1"); // Set multiple tags let mut tags = HashMap::new(); tags.insert("release".to_string(), "v1.2.3".to_string()); tags.insert("server".to_string(), "prod-1".to_string()); client.set_tags(tags); // Set extra data client.set_extra("request_id", json!("abc-123")); let mut extras = HashMap::new(); extras.insert("request_id".to_string(), json!("abc-123")); extras.insert("user_agent".to_string(), json!("Mozilla/5.0...")); client.set_extras(extras); ``` ## Actix-web Integration Example ```rust use actix_web::{web, App, HttpServer, HttpResponse}; use irontelemetry::{Client, BreadcrumbCategory}; use std::sync::Arc; struct AppState { telemetry: Arc, } async fn handler(data: web::Data) -> HttpResponse { data.telemetry.add_breadcrumb("Handler called", BreadcrumbCategory::Http); // Your logic here HttpResponse::Ok().body("Hello") } #[actix_web::main] async fn main() -> std::io::Result<()> { let client = Client::new("https://pk_live_xxx@irontelemetry.com") .expect("Failed to create client"); let app_state = web::Data::new(AppState { telemetry: client, }); HttpServer::new(move || { App::new() .app_data(app_state.clone()) .route("/", web::get().to(handler)) }) .bind("127.0.0.1:8080")? .run() .await } ``` ## Requirements - Rust 1.70+ - reqwest (HTTP client) - serde/serde_json (serialization) - chrono (timestamps) - uuid (event IDs) ## Links - [Documentation](https://www.irontelemetry.com/docs) - [Dashboard](https://www.irontelemetry.com) ## License MIT License - see [LICENSE](LICENSE) for details.