Add log_message, get_breadcrumbs, and ENABLE_DEBUG_LOGGING features

- Add log_message(level, title, message?, data?) for structured logging with title
- Add get_breadcrumbs() public method to retrieve current breadcrumbs
- Add ENABLE_DEBUG_LOGGING static AtomicBool and set_debug_logging() function
- Update all debug logging to respect the global debug flag

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
David Friedel 2025-12-26 11:32:08 +00:00
parent 09b9ae10c6
commit cc6ec51cdd
1 changed files with 41 additions and 3 deletions

View File

@ -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<String>,
message: Option<String>,
data: Option<HashMap<String, serde_json::Value>>,
) -> 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<String>, 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<Breadcrumb> {
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());