intelli_shell/
logging.rs

1use std::{env, fs::File, path::PathBuf};
2
3use color_eyre::{Result, eyre::Context};
4use tracing_error::ErrorLayer;
5use tracing_subscriber::{EnvFilter, fmt, prelude::*};
6
7use crate::config::Config;
8
9/// Resolves the log path and filter based on the config and environment variable.
10/// If logging is disabled, returns `None` for the filter.
11pub fn resolve_path_and_filter(config: &Config) -> (PathBuf, Option<String>) {
12    let env_filter = env::var("INTELLI_LOG").ok();
13    let logs_path = config.data_dir.join("intelli-shell.log");
14    let filter = (config.logs.enabled || env_filter.is_some())
15        .then(move || env_filter.unwrap_or_else(|| config.logs.filter.clone()));
16    (logs_path, filter)
17}
18
19/// Initializes the tracing subscriber to output logs to a file
20pub fn init(logs_path: PathBuf, filter: Option<String>) -> Result<()> {
21    if let Some(filter) = filter {
22        // Create the log file under the data dir
23        let log_file = File::create(&logs_path)
24            .wrap_err_with(|| format!("Couldn't create the log file: {}", logs_path.display()))?;
25        // Initialize the env filter
26        let env_filter = EnvFilter::builder()
27            .with_default_directive(tracing::Level::WARN.into())
28            .parse(filter)
29            .wrap_err("Couldn't parse the log filter")?;
30        // Subscribe logs to the file
31        let file_subscriber = fmt::layer()
32            .with_file(true)
33            .with_line_number(true)
34            .with_writer(log_file)
35            .with_target(false)
36            .with_ansi(false)
37            .with_filter(env_filter);
38        tracing_subscriber::registry()
39            .with(file_subscriber)
40            .with(ErrorLayer::default())
41            .init();
42    }
43    Ok(())
44}