use langfuse_ergonomic::{ClientBuilder, Result};
use reqwest_middleware::ClientBuilder as MiddlewareClientBuilder;
use reqwest_retry::{policies::ExponentialBackoff, RetryTransientMiddleware};
use serde_json::json;
#[tokio::main]
async fn main() -> Result<()> {
println!("=== HTTP Middleware with Retry Example ===\n");
println!("1. Creating Langfuse client with retry middleware\n");
let retry_policy = ExponentialBackoff::builder().build_with_max_retries(3);
let http_client = MiddlewareClientBuilder::new(reqwest::Client::new())
.with(RetryTransientMiddleware::new_with_policy(retry_policy))
.build();
let client = ClientBuilder::from_env()?
.http_client(http_client)
.build()?;
println!("Creating trace (retries are automatic)...");
match client
.trace()
.name("middleware-example")
.input(json!({"query": "Hello, world!"}))
.output(json!({"response": "Hi there!"}))
.tags(vec!["middleware".to_string(), "retry".to_string()])
.call()
.await
{
Ok(trace) => {
println!("\nSuccess! Trace created: {}", trace.id);
}
Err(e) => {
eprintln!("\nError after retries: {e}");
}
}
println!("\n2. Creating client with custom retry policy\n");
let custom_retry_policy = ExponentialBackoff::builder()
.retry_bounds(
std::time::Duration::from_millis(100), std::time::Duration::from_secs(30), )
.build_with_max_retries(5);
let custom_http_client = MiddlewareClientBuilder::new(
reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(60))
.build()
.expect("Failed to build reqwest client"),
)
.with(RetryTransientMiddleware::new_with_policy(
custom_retry_policy,
))
.build();
let custom_client = ClientBuilder::from_env()?
.http_client(custom_http_client)
.build()?;
println!("Creating trace with custom retry policy (up to 5 retries)...");
match custom_client
.trace()
.name("custom-retry-example")
.input(json!({"query": "Test with custom retry policy"}))
.metadata(json!({
"retry_config": {
"max_retries": 5,
"min_delay_ms": 100,
"max_delay_sec": 30
}
}))
.call()
.await
{
Ok(trace) => {
println!("\nSuccess! Trace created: {}", trace.id);
}
Err(e) => {
eprintln!("\nError after retries: {e}");
}
}
println!("\n3. Validating client credentials\n");
match client.validate().await {
Ok(true) => println!("Credentials validated successfully!"),
Ok(false) => println!("Credentials validation failed"),
Err(e) => eprintln!("Error validating credentials: {e}"),
}
println!("\n=== Example Complete ===");
println!("\nKey takeaways:");
println!("- Middleware allows transparent retry logic");
println!("- Exponential backoff prevents overwhelming the server");
println!("- Custom policies can be tailored to your needs");
println!("- All API calls automatically benefit from retries");
Ok(())
}