use std::fs;
use std::path::{Path, PathBuf};
use tracing_appender::non_blocking::WorkerGuard;
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
use tracing_subscriber::{EnvFilter, fmt};
pub fn get_log_dir(workspace_root: &Path) -> PathBuf {
workspace_root.join(".code-kb").join("logs")
}
pub fn init_logging(workspace_root: &Path, is_serve: bool, verbose: bool) -> Option<WorkerGuard> {
let log_dir = get_log_dir(workspace_root);
if let Err(e) = fs::create_dir_all(&log_dir) {
eprintln!(
"Warning: Failed to create log directory '{}': {e}",
log_dir.display()
);
return None;
}
let file_appender = match tracing_appender::rolling::RollingFileAppender::builder()
.rotation(tracing_appender::rolling::Rotation::DAILY)
.filename_prefix("code-kb.log")
.max_log_files(7)
.build(&log_dir)
{
Ok(appender) => appender,
Err(e) => {
eprintln!("Warning: Failed to initialize rolling file appender: {e}");
return None;
}
};
let (non_blocking_file, guard) = tracing_appender::non_blocking(file_appender);
let default_filter = if verbose {
"code_kb_core=debug,code_kb_cli=debug,code_kb=debug,info"
} else {
"code_kb_core=info,code_kb_cli=info,code_kb=info,warn"
};
let env_filter =
EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(default_filter));
let file_layer = fmt::layer()
.with_writer(non_blocking_file)
.with_ansi(false)
.with_target(true)
.with_thread_ids(true)
.with_file(true)
.with_line_number(true);
let stderr_layer = if !is_serve && (verbose || std::env::var_os("RUST_LOG").is_some()) {
Some(
fmt::layer()
.with_writer(std::io::stderr)
.with_ansi(true)
.with_target(false),
)
} else {
None
};
let subscriber = tracing_subscriber::registry()
.with(env_filter)
.with(file_layer)
.with(stderr_layer);
let _ = subscriber.try_init();
Some(guard)
}