Update README with branded header and documentation links
- Add centered logo and title with product branding - Add links to product website and documentation - Add badges for package manager and license - Add Other SDKs table with cross-references - Add Support section with dev@ironservices.io email - Update repository links to git.marketally.com 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
cc6ec51cdd
commit
2b6c218cbc
333
README.md
333
README.md
|
|
@ -1,14 +1,44 @@
|
||||||
# IronTelemetry SDK for Rust
|
<p align="center">
|
||||||
|
<a href="https://irontelemetry.com">
|
||||||
|
<img src="https://irontelemetry.com/logo.png" alt="IronTelemetry" width="120" />
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
Error monitoring and crash reporting SDK for Rust applications. Capture exceptions, track user journeys, and get insights to fix issues faster.
|
<h1 align="center">IronTelemetry SDK for Rust</h1>
|
||||||
|
|
||||||
[](https://crates.io/crates/irontelemetry)
|
<p align="center">
|
||||||
[](https://docs.rs/irontelemetry)
|
<strong>Error monitoring and crash reporting for Rust applications</strong>
|
||||||
[](https://opensource.org/licenses/MIT)
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://crates.io/crates/irontelemetry"><img src="https://img.shields.io/crates/v/irontelemetry.svg" alt="Crates.io"></a>
|
||||||
|
<a href="https://docs.rs/irontelemetry"><img src="https://docs.rs/irontelemetry/badge.svg" alt="Documentation"></a>
|
||||||
|
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://irontelemetry.com">Website</a> •
|
||||||
|
<a href="https://irontelemetry.com/docs">Documentation</a> •
|
||||||
|
<a href="https://irontelemetry.com/docs/rust">Rust Guide</a> •
|
||||||
|
<a href="https://git.marketally.com/ironservices">Git</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**IronTelemetry** helps you capture exceptions, track user journeys, and get actionable insights to fix issues faster. Built for developers who want simple, powerful error monitoring without the complexity.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Error Capture** - Capture errors with full context and metadata
|
||||||
|
- **Journey Tracking** - Understand what users did before an error occurred
|
||||||
|
- **Breadcrumbs** - Add context with custom breadcrumbs
|
||||||
|
- **Thread-Safe** - Safe for concurrent use with `Arc` and `RwLock`
|
||||||
|
- **Async Support** - Optional async feature for tokio/async-std
|
||||||
|
- **Zero-Copy** - Efficient memory usage with borrowed data where possible
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Add this to your `Cargo.toml`:
|
Add to your `Cargo.toml`:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
@ -24,91 +54,62 @@ irontelemetry = { version = "0.1", features = ["async"] }
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
### Basic Exception Capture
|
### Initialize the SDK
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use irontelemetry::{Client, SeverityLevel};
|
use irontelemetry::Client;
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
// Initialize with your DSN
|
|
||||||
let client = Client::new("https://pk_live_xxx@irontelemetry.com")?;
|
let client = Client::new("https://pk_live_xxx@irontelemetry.com")?;
|
||||||
|
|
||||||
// Capture a message
|
// Your application code
|
||||||
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Journey Tracking
|
### Capture Errors
|
||||||
|
|
||||||
Track user journeys to understand the context of errors:
|
```rust
|
||||||
|
if let Err(e) = do_something() {
|
||||||
|
client.capture_error(&*e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or capture with message
|
||||||
|
client.capture_exception("RuntimeError", "Something went wrong");
|
||||||
|
```
|
||||||
|
|
||||||
|
### Track User Journeys
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use irontelemetry::{Client, BreadcrumbCategory, create_journey_manager};
|
use irontelemetry::{Client, BreadcrumbCategory, create_journey_manager};
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
let journey_manager = create_journey_manager(&client);
|
||||||
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 journey = journey_manager.start_journey("Checkout Flow");
|
||||||
|
journey.set_user("user-123", Some("user@example.com"), Some("John Doe"));
|
||||||
|
|
||||||
let mut step = journey.start_step("Validate Cart", BreadcrumbCategory::Business);
|
let result = journey.run_step("Validate Cart", BreadcrumbCategory::Business, || {
|
||||||
step.set_data("cart_items", json!(5));
|
validate_cart()
|
||||||
|
});
|
||||||
|
|
||||||
match validate_cart() {
|
if let Err(e) = result {
|
||||||
Ok(_) => step.complete(),
|
journey.fail(Some(&e.to_string()));
|
||||||
Err(e) => {
|
client.capture_exception("ValidationError", &e.to_string());
|
||||||
step.fail(Some(&e.to_string()));
|
return Err(e.into());
|
||||||
journey.fail(Some(&e.to_string()));
|
|
||||||
return Err(e.into());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
journey.complete();
|
journey.complete();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Add Breadcrumbs
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use irontelemetry::BreadcrumbCategory;
|
||||||
|
|
||||||
|
client.add_breadcrumb("User clicked checkout button", BreadcrumbCategory::Ui);
|
||||||
|
client.add_breadcrumb("Payment API called", BreadcrumbCategory::Http);
|
||||||
|
```
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
|
@ -117,197 +118,31 @@ use irontelemetry::{Client, TelemetryOptions};
|
||||||
let options = TelemetryOptions::new("https://pk_live_xxx@irontelemetry.com")
|
let options = TelemetryOptions::new("https://pk_live_xxx@irontelemetry.com")
|
||||||
.environment("production")
|
.environment("production")
|
||||||
.app_version("1.2.3")
|
.app_version("1.2.3")
|
||||||
.sample_rate(1.0) // 100% of events
|
.sample_rate(1.0)
|
||||||
.debug(false)
|
.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)?;
|
let client = Client::with_options(options)?;
|
||||||
```
|
```
|
||||||
|
|
||||||
### Configuration Options
|
## Documentation
|
||||||
|
|
||||||
| Option | Type | Default | Description |
|
For complete documentation, visit [irontelemetry.com/docs](https://irontelemetry.com/docs).
|
||||||
|--------|------|---------|-------------|
|
|
||||||
| `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
|
## Other SDKs
|
||||||
|
|
||||||
- **Automatic Stack Traces**: Full stack traces captured with exceptions
|
| Platform | Package |
|
||||||
- **Journey Tracking**: Track user flows and correlate errors with context
|
|----------|---------|
|
||||||
- **Breadcrumbs**: Leave a trail of events leading up to an error
|
| JavaScript/TypeScript | [@ironservices/telemetry](https://git.marketally.com/ironservices/irontelemetry-js) |
|
||||||
- **User Context**: Associate errors with specific users
|
| .NET | [IronTelemetry.Client](https://git.marketally.com/ironservices/irontelemetry-dotnet) |
|
||||||
- **Tags & Extras**: Add custom metadata to your events
|
| Python | [irontelemetry](https://git.marketally.com/ironservices/irontelemetry-python) |
|
||||||
- **Thread-Safe**: All operations are safe for concurrent use with `Arc` and `RwLock`
|
| Go | [irontelemetry-go](https://git.marketally.com/ironservices/irontelemetry-go) |
|
||||||
- **Zero-Copy Where Possible**: Efficient memory usage with borrowed data
|
| Java | [irontelemetry-java](https://git.marketally.com/ironservices/irontelemetry-java) |
|
||||||
|
|
||||||
## Breadcrumbs
|
## Support
|
||||||
|
|
||||||
```rust
|
- **Documentation**: [irontelemetry.com/docs](https://irontelemetry.com/docs)
|
||||||
use irontelemetry::{BreadcrumbCategory, SeverityLevel};
|
- **Email**: dev@ironservices.io
|
||||||
use std::collections::HashMap;
|
- **Issues**: [git.marketally.com/ironservices/irontelemetry-rust/issues](https://git.marketally.com/ironservices/irontelemetry-rust/issues)
|
||||||
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<Client>,
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn handler(data: web::Data<AppState>) -> 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
|
## License
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue