Skip to main content

gitv_tui/
logging.rs

1use std::{env, path::PathBuf, sync::LazyLock};
2
3use directories::ProjectDirs;
4use tracing_error::ErrorLayer;
5use tracing_subscriber::{
6    EnvFilter, Layer,
7    fmt::{self},
8    layer::SubscriberExt,
9    util::SubscriberInitExt,
10};
11
12use crate::{app::cli::LogLevel, errors::AppError};
13
14pub static PROJECT_NAME: LazyLock<String> =
15    LazyLock::new(|| env!("CARGO_CRATE_NAME").to_uppercase().to_string());
16pub static DATA_FOLDER: LazyLock<Option<PathBuf>> = LazyLock::new(|| {
17    env::var(format!("{}_DATA", &*PROJECT_NAME))
18        .ok()
19        .map(PathBuf::from)
20});
21
22pub static LOG_ENV: LazyLock<String> = LazyLock::new(|| format!("{}_LOG_LEVEL", &*PROJECT_NAME));
23pub static LOG_FILE: LazyLock<String> = LazyLock::new(|| format!("{}.log", env!("CARGO_PKG_NAME")));
24
25pub fn get_data_dir() -> PathBuf {
26    if let Some(s) = DATA_FOLDER.clone() {
27        s
28    } else if let Some(proj_dirs) = project_directory() {
29        proj_dirs.data_local_dir().to_path_buf()
30    } else {
31        PathBuf::from(".").join(".data")
32    }
33}
34
35pub(crate) fn project_directory() -> Option<ProjectDirs> {
36    ProjectDirs::from("com", "jayanaxhf", env!("CARGO_PKG_NAME"))
37}
38
39pub fn init(cfg: LoggingConfig) -> Result<(), AppError> {
40    //TODO: Add proper directory for logs
41    let directory = get_data_dir();
42    std::fs::create_dir_all(directory.clone())?;
43    let log_path = directory.join(&*LOG_FILE);
44    let log_file = std::fs::File::create(log_path)?;
45
46    let env_filter = EnvFilter::builder()
47        .with_default_directive(cfg.level.try_into().map_err(anyhow::Error::from)?);
48    // If the `RUST_LOG` environment variable is set, use that as the default, otherwise use the
49    // value of the `LOG_ENV` environment variable. If the `LOG_ENV` environment variable contains
50    // errors, then this will return an error.
51    let env_filter = env_filter
52        .try_from_env()
53        .or_else(|_| env_filter.with_env_var(LOG_ENV.clone()).from_env())
54        .map_err(Into::<anyhow::Error>::into)?;
55    let file_subscriber = fmt::layer()
56        .with_file(true)
57        .with_line_number(true)
58        .with_writer(log_file)
59        .with_ansi(false)
60        .with_target(true)
61        .with_filter(env_filter);
62    tracing_subscriber::registry()
63        .with(file_subscriber)
64        .with(ErrorLayer::default())
65        .try_init()?;
66
67    Ok(())
68}
69
70#[derive(Clone, Debug)]
71pub struct LoggingConfig {
72    level: LogLevel,
73}
74
75impl LoggingConfig {
76    pub fn new(level: LogLevel) -> Self {
77        Self { level }
78    }
79}