use anyhow::Result;
use kerf::{Config, Kerf, Match};
use std::fs::OpenOptions;
use std::io::Write;
use std::sync::{Arc, Mutex};
use tracing::{debug, error, info, warn};
#[tokio::main]
async fn main() -> Result<()> {
println!("🎯 Kerf Builder Pattern Demo");
println!("This example demonstrates the new per-tab callback functionality");
println!("where each tab can have its own dedicated callback function.\n");
let log_file = Arc::new(Mutex::new(
OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open("/tmp/kerf_errors.log")?,
));
let config = Config::empty()
.with_tab("console", Match::info().all_modules())
.with_tab("errors", Match::error().all_modules())
.with_tab("debug", Match::debug().module_pattern("demo::*"));
let log_file_clone = Arc::clone(&log_file);
Kerf::init(config)?
.with_tab_callback("console", |event| {
println!("📺 CONSOLE: {}", event.format());
})
.with_tab_callback("errors", move |event| {
eprintln!("❌ ERROR: {}", event.format());
if let Ok(mut file) = log_file_clone.lock() {
writeln!(file, "[{}] {}", event.timestamp, event.format_full()).ok();
file.flush().ok();
}
})
.with_tab_callback("debug", |event| {
println!(
"🐛 DEBUG: {} ({}:{})",
event.message,
event.file.as_deref().unwrap_or("unknown"),
event.line.unwrap_or(0)
);
})
.build()
.await?;
println!("✅ Kerf initialized with per-tab callbacks!\n");
info!("Application starting up");
debug!(target: "demo::startup", "Loading configuration files");
warn!("This warning won't be captured by any tab");
error!("Failed to connect to database");
info!("Retrying database connection");
debug!(target: "demo::database", "Connection pool initialized");
error!("Critical system error occurred");
tokio::time::sleep(tokio::time::Duration::from_millis(500)).await;
println!("\n🎉 Demo completed!");
println!("📁 Error log written to: /tmp/kerf_errors.log");
let error_log = std::fs::read_to_string("/tmp/kerf_errors.log")?;
if !error_log.is_empty() {
println!("\n📋 Error log contents:");
println!("{error_log}");
}
println!("\n💡 Key benefits of the builder pattern:");
println!(" • Each tab has its own dedicated callback");
println!(" • No more complex routing logic in a single callback");
println!(" • Config remains fully serializable");
println!(" • Clean separation of concerns");
println!(" • Easy to compose and reuse tab configurations");
Ok(())
}