preamble2 0.0.1

Modern rust project manager library re-written from the ground up.
Documentation
//! Telemetry module.
//!
//! The telemetry module contains convenience functions for setting up tracing
//! in workspace projects generated by amble. This reduces boilerplate code in
//! downstream project binaries and libraries.
//!
//! # Usage
//!
//! Most users will want to use the [`init_default_tracing`] function to
//! initialize the tracing subscriber with the verbosity level read from the
//! `RUST_LOG` environment variable.
//!
//! ```rust
//! use preamble2::telemetry;
//!
//! telemetry::init_default_tracing().unwrap();
//! // ...
//! tracing::info!("Hello, world!");
//! // ...
//! ```
//!
//! _Notice, since the verbosity defaults to 0 (errors), "Hello World" will not
//! be printed unless the `RUST_LOG` environment variable is set to 2 or higher._
//!
//! If you want to set the verbosity level manually, you can use the
//! [`init_tracing_subscriber`] function.
//!
//! ```rust
//! use preamble2::telemetry;
//! use preamble2::Level;
//!
//! telemetry::init_tracing_subscriber(Level::INFO).unwrap();
//! // ...
//! tracing::info!("Hello, world!");
//! // ...
//! ```

use anyhow::Result;
use tracing_subscriber::EnvFilter;

/// Level
///
/// A convenience level that implements [`From<u8>`] and [`From<tracing::Level>`].
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Level {
    /// ERROR
    ERROR = 0,
    /// WARN
    WARN = 1,
    /// INFO
    INFO = 2,
    /// DEBUG
    DEBUG = 3,
    /// TRACE
    TRACE = 4,
}

impl From<u8> for Level {
    fn from(v: u8) -> Self {
        match v {
            0 => Self::ERROR,
            1 => Self::WARN,
            2 => Self::INFO,
            3 => Self::DEBUG,
            _ => Self::TRACE,
        }
    }
}

impl From<Level> for u8 {
    fn from(v: Level) -> Self {
        v as u8
    }
}

impl From<tracing::Level> for Level {
    fn from(v: tracing::Level) -> Self {
        match v {
            tracing::Level::ERROR => Self::ERROR,
            tracing::Level::WARN => Self::WARN,
            tracing::Level::INFO => Self::INFO,
            tracing::Level::DEBUG => Self::DEBUG,
            tracing::Level::TRACE => Self::TRACE,
        }
    }
}

/// Initializes the tracing subscriber.
///
/// The verbosity level determines the maximum level of tracing.
/// - 0: ERROR
/// - 1: WARN
/// - 2: INFO
/// - 3: DEBUG
/// - 4+: TRACE
///
/// # Arguments
/// * `verbosity` - The verbosity level (0-4)
///
/// # Returns
/// * [`anyhow::Result<()>`] - Ok if successful, Err otherwise.
pub fn init_tracing_subscriber(verbosity: impl Into<u8>) -> Result<()> {
    let subscriber = tracing_subscriber::fmt()
        .with_max_level(match verbosity.into() {
            0 => tracing::Level::ERROR,
            1 => tracing::Level::WARN,
            2 => tracing::Level::INFO,
            3 => tracing::Level::DEBUG,
            _ => tracing::Level::TRACE,
        })
        .finish();
    tracing::subscriber::set_global_default(subscriber).map_err(|e| anyhow::anyhow!(e))
}

/// Initializes the tracing subscriber with an environment variable filter.
///
/// The verbosity level is read from the `RUST_LOG` environment variable.
/// - 0: ERROR
/// - 1: WARN
/// - 2: INFO
/// - 3: DEBUG
/// - 4+: TRACE
///
/// # Arguments
/// * `verbosity` - The verbosity level (0-4)
///
/// # Returns
/// * [`anyhow::Result<()>`] - Ok if successful, Err otherwise.
pub fn init_tracing_subscriber_with_env(verbosity: impl Into<u8>) -> Result<()> {
    let subscriber = tracing_subscriber::fmt()
        .with_max_level(match verbosity.into() {
            0 => tracing::Level::ERROR,
            1 => tracing::Level::WARN,
            2 => tracing::Level::INFO,
            3 => tracing::Level::DEBUG,
            _ => tracing::Level::TRACE,
        })
        .with_env_filter(EnvFilter::from_default_env())
        .finish();
    tracing::subscriber::set_global_default(subscriber).map_err(|e| anyhow::anyhow!(e))
}

/// Builds and sets the default global tracing subscriber.
/// The verbosity level is read from the `RUST_LOG` environment variable.
pub fn init_default_tracing() -> Result<()> {
    let rust_log = std::env::var("RUST_LOG");
    let v = rust_log.map_or(0, |v| v.parse::<u8>().unwrap_or(0));
    init_tracing_subscriber_with_env(v)
}