logtail-rust 0.3.0

Logtail http client wrapper
Documentation
use serde::Serialize;
use std::fmt::{Display, Formatter};

use crate::r#struct::env_config::{EnvConfig, EnvEnum};
use crate::r#struct::log_level::LogLevel;

#[derive(Debug, Serialize, Clone)]
pub struct BetterStackLogSchema {
    pub env: EnvEnum,
    pub message: String,
    pub context: String,
    pub level: LogLevel,
    pub app_version: String,
}

impl Display for BetterStackLogSchema {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        let self_json = serde_json::to_string(self).unwrap();
        write!(f, "{}", self_json)
    }
}

impl BetterStackLogSchema {
    pub(crate) fn new(
        env_config: &EnvConfig,
        level: LogLevel,
        message: String,
        context: String,
    ) -> Self {
        Self {
            env: env_config.environment.clone(),
            message,
            context,
            level,
            app_version: env_config.app_version.clone(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn sample_schema() -> BetterStackLogSchema {
        BetterStackLogSchema {
            env: EnvEnum::QA,
            message: "test message".to_string(),
            context: "test context".to_string(),
            level: LogLevel::Info,
            app_version: "1.0.0".to_string(),
        }
    }

    #[test]
    fn display_outputs_valid_json() {
        let schema = sample_schema();
        let output = schema.to_string();
        let parsed: serde_json::Value = serde_json::from_str(&output).unwrap();
        assert!(parsed.is_object());
    }

    #[test]
    fn display_contains_all_fields() {
        let schema = sample_schema();
        let output = schema.to_string();
        let parsed: serde_json::Value = serde_json::from_str(&output).unwrap();
        let obj = parsed.as_object().unwrap();

        assert!(obj.contains_key("env"));
        assert!(obj.contains_key("message"));
        assert!(obj.contains_key("context"));
        assert!(obj.contains_key("level"));
        assert!(obj.contains_key("app_version"));
    }

    #[test]
    fn display_field_values_match() {
        let schema = sample_schema();
        let output = schema.to_string();
        let parsed: serde_json::Value = serde_json::from_str(&output).unwrap();

        assert_eq!(parsed["message"], "test message");
        assert_eq!(parsed["context"], "test context");
        assert_eq!(parsed["app_version"], "1.0.0");
        assert_eq!(parsed["env"], "QA");
        assert_eq!(parsed["level"], "Info");
    }

    #[test]
    fn clone_produces_equal_fields() {
        let schema = sample_schema();
        let cloned = schema.clone();

        assert_eq!(schema.env, cloned.env);
        assert_eq!(schema.message, cloned.message);
        assert_eq!(schema.context, cloned.context);
        assert_eq!(schema.level, cloned.level);
        assert_eq!(schema.app_version, cloned.app_version);
    }

    #[test]
    fn serde_serialize_contains_expected_keys() {
        let schema = sample_schema();
        let value = serde_json::to_value(&schema).unwrap();
        let obj = value.as_object().unwrap();

        assert_eq!(obj.len(), 5);
        assert_eq!(obj["message"], "test message");
        assert_eq!(obj["context"], "test context");
        assert_eq!(obj["level"], "Info");
        assert_eq!(obj["env"], "QA");
        assert_eq!(obj["app_version"], "1.0.0");
    }

    #[test]
    fn new_maps_fields_from_env_config() {
        let config = EnvConfig {
            app_version: "2.5.0".to_string(),
            environment: EnvEnum::Prod,
            logs_source_token: "token".to_string(),
            verbose: false,
        };

        let schema = BetterStackLogSchema::new(
            &config,
            LogLevel::Error,
            "err msg".to_string(),
            "err ctx".to_string(),
        );

        assert_eq!(schema.env, EnvEnum::Prod);
        assert_eq!(schema.message, "err msg");
        assert_eq!(schema.context, "err ctx");
        assert_eq!(schema.level, LogLevel::Error);
        assert_eq!(schema.app_version, "2.5.0");
    }
}