veecle_telemetry/log.rs
1//! Structured logging functionality with multiple severity levels.
2//!
3//! This module provides the core logging infrastructure for the telemetry system.
4//! It supports structured logging with key-value attributes and automatically
5//! correlates log messages with active spans when available.
6//!
7//! # Severity Levels
8//!
9//! The logging system supports multiple severity levels:
10//! - [`Severity::Trace`] - Very detailed debugging information
11//! - [`Severity::Debug`] - Detailed debugging information
12//! - [`Severity::Info`] - General informational messages
13//! - [`Severity::Warn`] - Warning messages for potential issues
14//! - [`Severity::Error`] - Error messages for serious problems
15//! - [`Severity::Fatal`] - Fatal error messages for critical failures
16//!
17//! # Examples
18//!
19//! ```rust
20//! veecle_telemetry::info!("Operation completed", {
21//! "duration_ms" = 150,
22//! "success" = true
23//! });
24//! ```
25
26use crate::KeyValue;
27#[cfg(feature = "enable")]
28use crate::SpanContext;
29#[cfg(feature = "enable")]
30use crate::collector::get_collector;
31use crate::protocol::Severity;
32#[cfg(feature = "enable")]
33use crate::protocol::{LogMessage, attribute_list_from_slice};
34#[cfg(feature = "enable")]
35use crate::time::now;
36
37/// Logs a message with the specified severity level and attributes.
38///
39/// Prefer using the macros.
40///
41/// This function creates a log message with the given severity, body text, and
42/// key-value attributes.
43/// If there is an active span context, the log message
44/// will automatically be correlated with the trace and span IDs.
45///
46/// # Arguments
47///
48/// * `severity` - The severity level of the log message
49/// * `body` - The main message text
50/// * `attributes` - Key-value pairs providing additional context
51///
52/// # Examples
53///
54/// ```rust
55/// use veecle_telemetry::log::log;
56/// use veecle_telemetry::protocol::Severity;
57/// use veecle_telemetry::{KeyValue, Value, span};
58///
59/// // Simple log message
60/// log(Severity::Info, "Server started", &[]);
61///
62/// // Log with attributes
63/// log(Severity::Warn, "High memory usage", &[
64/// KeyValue::new("memory_usage_percent", 85),
65/// KeyValue::new("available_mb", 512),
66/// ]);
67///
68/// // Log within a span context
69/// let span = span!("request_handler");
70/// let _guard = span.entered();
71/// log(Severity::Error, "Request failed", &[KeyValue::new("error_code", 500)]);
72/// ```
73///
74/// # Conditional Compilation
75///
76/// When the `enable` feature is disabled, this function compiles to a no-op
77/// and has zero runtime overhead.
78#[doc(hidden)]
79pub fn log(severity: Severity, body: &'static str, attributes: &'_ [KeyValue<'static>]) {
80 #[cfg(not(feature = "enable"))]
81 {
82 let _ = (severity, body, attributes);
83 }
84
85 #[cfg(feature = "enable")]
86 {
87 let current_context = SpanContext::current();
88 let (trace_id, span_id) = if let Some(context) = current_context {
89 (Some(context.trace_id), Some(context.span_id))
90 } else {
91 (None, None)
92 };
93
94 let log_message = LogMessage {
95 time_unix_nano: now().as_nanos(),
96 severity,
97 body: body.into(),
98 attributes: attribute_list_from_slice(attributes),
99 trace_id,
100 span_id,
101 };
102
103 get_collector().log_message(log_message);
104 }
105}