use std::sync::Arc;
use std::time::Duration;
use tracing::{error, info, warn};
use tracing_subscriber::prelude::*;
use tracing_throttle::{
Policy, RedisStorage, RedisStorageConfig, SystemClock, TracingRateLimitLayer,
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let redis_config = RedisStorageConfig {
key_prefix: "tracing_throttle".to_string(),
ttl: Duration::from_secs(300), };
let storage = RedisStorage::connect_with_config("redis://127.0.0.1:6379", redis_config).await?;
let policy = Policy::token_bucket(50.0, 5.0)?;
let clock = Arc::new(SystemClock::new());
let rate_limit = TracingRateLimitLayer::with_storage(storage, policy, clock);
tracing_subscriber::registry()
.with(tracing_subscriber::fmt::layer().with_filter(rate_limit))
.init();
info!("Starting Redis-backed rate limiting example");
info!("Redis storage allows multiple processes to share rate limits");
info!("");
info!("=== Burst Test (identical logs) ===");
for _ in 1..=100 {
info!(message = "Burst event", "Repeated event");
}
tokio::time::sleep(Duration::from_millis(500)).await;
info!("");
info!("=== Multi-Level Test (different signatures) ===");
for _ in 1..=30 {
info!(event = "info", "Info level event");
warn!(event = "warn", "Warning level event");
error!(event = "error", "Error level event");
}
tokio::time::sleep(Duration::from_millis(500)).await;
info!("");
info!("=== Field Variation Test ===");
for user_id in 1..=20 {
info!(user_id = user_id, "User action logged");
info!(user_id = user_id, "User action logged"); info!(user_id = user_id, "User action logged"); }
tokio::time::sleep(Duration::from_millis(500)).await;
info!("");
info!("=== Token Refill Test ===");
info!("Waiting 2 seconds for token refill (10 tokens at 5/sec)...");
tokio::time::sleep(Duration::from_secs(2)).await;
for _ in 1..=15 {
info!("After refill");
}
tokio::time::sleep(Duration::from_secs(1)).await;
info!("");
info!("=== Example Complete ===");
info!("Rate limiting state is persisted in Redis");
info!("Try running this example again immediately to see shared state");
tokio::time::sleep(Duration::from_secs(2)).await;
Ok(())
}