diff --git a/src/client.rs b/src/client.rs index c6f8549..2368b6a 100644 --- a/src/client.rs +++ b/src/client.rs @@ -7,8 +7,18 @@ use crate::types::{ TelemetryEvent, User, }; use std::collections::HashMap; +use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, RwLock, Weak}; +/// Global debug logging flag. When enabled, all IronTelemetry clients +/// will output debug information to stdout. +pub static ENABLE_DEBUG_LOGGING: AtomicBool = AtomicBool::new(false); + +/// Enable or disable global debug logging for all TelemetryClient instances. +pub fn set_debug_logging(enabled: bool) { + ENABLE_DEBUG_LOGGING.store(enabled, Ordering::SeqCst); +} + /// The main IronTelemetry client. pub struct Client { options: TelemetryOptions, @@ -31,7 +41,7 @@ impl Client { let api_base_url = options.api_base_url.as_deref(); let transport = Transport::new(&parsed_dsn, api_base_url, options.debug); - if options.debug { + if options.debug || ENABLE_DEBUG_LOGGING.load(Ordering::SeqCst) { println!("[IronTelemetry] Initialized with DSN: {}", parsed_dsn.api_base_url); } @@ -69,6 +79,29 @@ impl Client { self.send_event(event) } + /// Log a structured message with title, message, and optional data. + /// Useful for structured logging that differentiates the log title from its details. + pub fn log_message( + &self, + level: SeverityLevel, + title: impl Into, + message: Option, + data: Option>, + ) -> SendResult { + let title_str = title.into(); + let full_message = match &message { + Some(msg) if !msg.is_empty() => format!("{}: {}", title_str, msg), + _ => title_str.clone(), + }; + + let mut event = self.create_event(level, Some(full_message)); + event.extra.insert("logTitle".to_string(), serde_json::json!(title_str)); + if let Some(d) = data { + event.extra.insert("logData".to_string(), serde_json::json!(d)); + } + self.send_event(event) + } + /// Add a breadcrumb. pub fn add_breadcrumb(&self, message: impl Into, category: BreadcrumbCategory) { self.breadcrumbs.add_simple(message, category); @@ -139,6 +172,11 @@ impl Client { self.breadcrumbs.clear(); } + /// Get a copy of the current breadcrumbs list. + pub fn get_breadcrumbs(&self) -> Vec { + self.breadcrumbs.get_all() + } + /// Flush pending events. pub fn flush(&self) { // Future: Implement offline queue flushing @@ -167,7 +205,7 @@ impl Client { if self.options.sample_rate < 1.0 { let random: f64 = rand::random(); if random > self.options.sample_rate { - if self.options.debug { + if self.options.debug || ENABLE_DEBUG_LOGGING.load(Ordering::SeqCst) { println!("[IronTelemetry] Event sampled out: {}", event.event_id); } return SendResult::success(event.event_id); @@ -179,7 +217,7 @@ impl Client { match before_send(event) { Some(e) => event = e, None => { - if self.options.debug { + if self.options.debug || ENABLE_DEBUG_LOGGING.load(Ordering::SeqCst) { println!("[IronTelemetry] Event dropped by beforeSend hook"); } return SendResult::success("".to_string());