telemetry-kit

Auto-Sync

Configure automatic background synchronization for telemetry events

Overview

Auto-sync automatically synchronizes your telemetry events to the server in the background, eliminating the need for manual .sync() calls.

Auto-sync is enabled by default when you configure sync credentials.

Quick Start

use telemetry_kit::prelude::*;
 
#[tokio::main]
async fn main() -> Result<()> {
    let telemetry = TelemetryKit::builder()
        .service_name("my-app")?
        .with_sync_credentials(org_id, app_id, token, secret)?
        .build()?;  // Auto-sync starts automatically!
 
    // Track events - they sync in the background
    telemetry.track_command("build", |event| {
        event.success(true).duration_ms(1234)
    }).await?;
 
    // Graceful shutdown with final sync
    telemetry.shutdown().await?;
 
    Ok(())
}

Configuration

Sync Interval

Configure how often events are synced (default: 60 seconds):

let telemetry = TelemetryKit::builder()
    .service_name("my-app")?
    .with_sync_credentials(org_id, app_id, token, secret)?
    .sync_interval(30)  // Sync every 30 seconds
    .build()?;

Sync on Shutdown

Control whether a final sync happens when dropping the telemetry instance (default: true):

let telemetry = TelemetryKit::builder()
    .service_name("my-app")?
    .with_sync_credentials(org_id, app_id, token, secret)?
    .sync_on_shutdown(true)  // Sync before exit
    .build()?;

Disable Auto-Sync

If you prefer manual control:

let telemetry = TelemetryKit::builder()
    .service_name("my-app")?
    .with_sync_credentials(org_id, app_id, token, secret)?
    .auto_sync(false)  // Disable auto-sync
    .build()?;
 
// Manual sync when needed
telemetry.sync().await?;

How It Works

Background Task

When auto-sync is enabled, telemetry-kit spawns a background tokio task that:

  1. Waits for the configured interval
  2. Retrieves unsynced events from SQLite
  3. Sends them to the server in batches
  4. Marks successfully synced events
  5. Repeats

Thread Safety

The auto-sync implementation is thread-safe:

  • Uses Arc<Mutex<AutoSyncTask>> for safe concurrent access
  • Storage operations protected by RwLock
  • Atomic bool for shutdown signaling

Graceful Shutdown

Call .shutdown() for graceful cleanup:

telemetry.shutdown().await?;

This will:

  1. Stop the background task
  2. Perform a final sync (if sync_on_shutdown is true)
  3. Wait for the task to complete

The Drop implementation will stop the background task automatically, but it cannot perform async operations. For guaranteed final sync, call .shutdown() explicitly.

Advanced Configuration

Full Configuration Example

let telemetry = TelemetryKit::builder()
    .service_name("my-app")?
    .service_version("1.0.0")
    .with_sync_credentials(
        "my-org",
        "my-app",
        "token_abc123",
        "secret_xyz789"
    )?
    .auto_sync(true)            // Enable auto-sync
    .sync_interval(60)          // Sync every 60 seconds
    .sync_on_shutdown(true)     // Sync before exit
    .build()?;

Custom Sync Configuration

For more control over sync behavior, use SyncConfig:

use telemetry_kit::sync::SyncConfig;
 
let sync_config = SyncConfig::builder()
    .org_id("my-org")?
    .app_id("my-app")?
    .token("token_abc123")
    .secret("secret_xyz789")
    .endpoint("https://custom.endpoint.com/ingest")
    .batch_size(200)  // Send up to 200 events per sync
    .build()?;
 
let telemetry = TelemetryKit::builder()
    .service_name("my-app")?
    .sync(sync_config)
    .auto_sync(true)
    .build()?;

Best Practices

Interval Selection

Choose your sync interval based on your needs:

  • High-frequency apps (CLI tools): 5-15 seconds
  • Normal apps: 60 seconds (default)
  • Low-priority telemetry: 300 seconds (5 minutes)
// CLI tool - sync quickly
.sync_interval(10)
 
// Background service - less frequent
.sync_interval(300)

Handling Failures

Auto-sync includes automatic retry with exponential backoff:

  1. Failed sync attempts are automatically retried
  2. Retry count tracked per event
  3. Events persist until successfully synced
  4. No data loss even with network issues

DO_NOT_TRACK

Auto-sync respects the DO_NOT_TRACK environment variable:

# Disable all telemetry
DO_NOT_TRACK=1 cargo run

Examples

Example 1: CLI Application

use telemetry_kit::prelude::*;
 
#[tokio::main]
async fn main() -> Result<()> {
    let telemetry = TelemetryKit::builder()
        .service_name("my-cli")?
        .with_sync_credentials(
            std::env::var("TELEMETRY_ORG_ID")?,
            std::env::var("TELEMETRY_APP_ID")?,
            std::env::var("TELEMETRY_TOKEN")?,
            std::env::var("TELEMETRY_SECRET")?,
        )?
        .sync_interval(5)  // Quick sync for CLI
        .build()?;
 
    // Your CLI logic here
 
    telemetry.shutdown().await?;
    Ok(())
}

Example 2: Long-Running Service

use telemetry_kit::prelude::*;
use tokio::signal;
 
#[tokio::main]
async fn main() -> Result<()> {
    let telemetry = TelemetryKit::builder()
        .service_name("my-service")?
        .with_sync_credentials(org_id, app_id, token, secret)?
        .sync_interval(60)  // Sync every minute
        .build()?;
 
    // Start your service
    let service = start_service(telemetry.clone());
 
    // Wait for shutdown signal
    signal::ctrl_c().await?;
 
    // Graceful shutdown
    telemetry.shutdown().await?;
    service.shutdown().await?;
 
    Ok(())
}

Example 3: Conditional Auto-Sync

let enable_sync = std::env::var("ENABLE_TELEMETRY")
    .map(|v| v == "true")
    .unwrap_or(false);
 
let mut builder = TelemetryKit::builder()
    .service_name("my-app")?;
 
if enable_sync {
    builder = builder
        .with_sync_credentials(org_id, app_id, token, secret)?
        .auto_sync(true);
}
 
let telemetry = builder.build()?;

Troubleshooting

Events Not Syncing

  1. Check auto-sync is enabled:
.auto_sync(true)
  1. Verify credentials are correct:
telemetry-kit test
  1. Check network connectivity to the server

  2. View unsynced events:

telemetry-kit stats

High Memory Usage

If you're generating events faster than they can sync:

  1. Increase sync interval:
.sync_interval(10)  // Sync more frequently
  1. Increase batch size:
SyncConfig::builder()
    .batch_size(500)  // Larger batches
  1. Implement event sampling for high-volume scenarios

Performance

Overhead

  • Memory: ~1KB per background task
  • CPU: Negligible at rest (task sleeps between intervals)
  • Network: Batched requests minimize overhead

Benchmarks

IntervalEvents/secMemoryCPU
5s1000<5MB<1%
60s1000<5MB<0.1%
300s1000<5MB<0.1%

See Also

On this page