veecle_telemetry/
macros.rs

1/// Creates a new span.
2///
3/// A span represents a unit of work or operation that has a beginning and end.
4/// It can contain attributes that provide additional context about the operation.
5///
6/// # Examples
7///
8/// ```rust
9/// use veecle_telemetry::span;
10///
11/// let span = span!("database_query");
12/// ```
13///
14/// ```rust
15/// use veecle_telemetry::span;
16///
17/// let user_id = 123;
18/// let table_name = "users";
19/// let span =
20///     span!("database_query", user_id, table = table_name, "operation" = "select");
21/// ```
22#[macro_export]
23macro_rules! span {
24    ($name:literal $(, $($attributes:tt)*)?) => {
25        $crate::Span::new($name, $crate::attributes!($($($attributes)*)?))
26    };
27}
28
29/// Adds an event to the current span.
30///
31/// Events are timestamped occurrences that happen during the execution of a span.
32/// They can include additional context through attributes.
33///
34/// # Examples
35///
36/// Add a simple event:
37/// ```rust
38/// use veecle_telemetry::event;
39///
40/// event!("cache_miss");
41/// ```
42///
43/// Add an event with attributes:
44/// ```rust
45/// use veecle_telemetry::event;
46///
47/// let key = "user:123";
48/// let cache_type = "redis";
49/// event!("cache_miss", key = key, cache_type = cache_type, "retry_count" = 3);
50/// ```
51#[macro_export]
52macro_rules! event {
53    ($name:literal $(, $($attributes:tt)*)?) => {
54        $crate::CurrentSpan::add_event($name, $crate::attributes!($($($attributes)*)?))
55    };
56}
57
58/// Logs a message with the specified severity level.
59///
60/// This is the base logging macro that other severity-specific macros build upon.
61/// It allows you to specify the severity level and optional attributes.
62///
63/// # Examples
64///
65/// Log a simple message:
66/// ```rust
67/// use veecle_telemetry::log;
68/// use veecle_telemetry::protocol::base::Severity;
69///
70/// log!(Severity::Info, "Application started");
71/// ```
72///
73/// Log a message with attributes:
74/// ```rust
75/// use veecle_telemetry::log;
76/// use veecle_telemetry::protocol::base::Severity;
77///
78/// let port = 8080;
79/// let version = "1.0.0";
80/// log!(Severity::Info, "Server listening", port = port, version = version, "protocol" = "HTTP");
81/// ```
82#[macro_export]
83macro_rules! log {
84    ($severity:expr, $body:literal $(, $($attributes:tt)*)?) => {
85        $crate::log::log($severity, $body, $crate::attributes!($($($attributes)*)?))
86    };
87}
88
89/// Logs a trace-level message.
90///
91/// Trace messages are used for very detailed debugging information,
92/// typically only enabled during development or deep troubleshooting.
93///
94/// # Examples
95///
96/// Simple trace message:
97/// ```rust
98/// use veecle_telemetry::trace;
99///
100/// trace!("Entering function");
101/// ```
102///
103/// Trace message with context:
104/// ```rust
105/// use veecle_telemetry::trace;
106///
107/// let function_name = "process_request";
108/// let request_id = "req-123";
109/// trace!("Function entry", function = function_name, request_id = request_id);
110/// ```
111#[macro_export]
112macro_rules! trace {
113    ($($args:tt)*) => {
114        $crate::log!($crate::protocol::base::Severity::Trace, $($args)*);
115    };
116}
117
118/// Logs a debug-level message.
119///
120/// Debug messages provide detailed information about the program's execution,
121/// useful for diagnosing issues during development and testing.
122///
123/// # Examples
124///
125/// Simple debug message:
126/// ```rust
127/// use veecle_telemetry::debug;
128///
129/// debug!("Processing user request");
130/// ```
131///
132/// Debug message with variables:
133/// ```rust
134/// use veecle_telemetry::debug;
135///
136/// let user_id = 456;
137/// let action = "login";
138/// debug!("User action processed", user_id = user_id, action = action, "success" = true);
139/// ```
140#[macro_export]
141macro_rules! debug {
142    ($($args:tt)*) => {
143        $crate::log!($crate::protocol::base::Severity::Debug, $($args)*);
144    };
145}
146
147/// Logs an info-level message.
148///
149/// Info messages provide general information about the program's execution,
150/// suitable for normal operational logging.
151///
152/// # Examples
153///
154/// Simple info message:
155/// ```rust
156/// use veecle_telemetry::info;
157///
158/// info!("Service started successfully");
159/// ```
160///
161/// Info message with metadata:
162/// ```rust
163/// use veecle_telemetry::info;
164///
165/// let service_name = "web-server";
166/// let version = "2.1.0";
167/// info!(
168///     "Service initialization complete",
169///     service = service_name,
170///     version = version,
171///     "startup_time_ms" = 1250
172/// );
173/// ```
174#[macro_export]
175macro_rules! info {
176    ($($args:tt)*) => {
177        $crate::log!($crate::protocol::base::Severity::Info, $($args)*);
178    };
179}
180
181/// Logs a warning-level message.
182///
183/// Warning messages indicate potential issues or unusual conditions
184/// that don't prevent the program from continuing but should be noted.
185///
186/// # Examples
187///
188/// Simple warning message:
189/// ```rust
190/// use veecle_telemetry::warn;
191///
192/// warn!("Rate limit approaching");
193/// ```
194///
195/// Warning with context:
196/// ```rust
197/// use veecle_telemetry::warn;
198///
199/// let current_requests = 950;
200/// let limit = 1000;
201/// warn!(
202///     "High request rate detected",
203///     current_requests = current_requests,
204///     limit = limit,
205///     "utilization_percent" = 95
206/// );
207/// ```
208#[macro_export]
209macro_rules! warn {
210    ($($args:tt)*) => {
211        $crate::log!($crate::protocol::base::Severity::Warn, $($args)*);
212    };
213}
214
215/// Logs an error-level message.
216///
217/// Error messages indicate serious problems that have occurred
218/// but allow the program to continue running.
219///
220/// # Examples
221///
222/// Simple error message:
223/// ```rust
224/// use veecle_telemetry::error;
225///
226/// error!("Database connection failed");
227/// ```
228///
229/// Error with details:
230/// ```rust
231/// use veecle_telemetry::error;
232///
233/// let db_host = "localhost:5432";
234/// let error_code = 1001;
235/// error!(
236///     "Database operation failed",
237///     host = db_host,
238///     error_code = error_code,
239///     "retry_attempted" = true
240/// );
241/// ```
242#[macro_export]
243macro_rules! error {
244    ($($args:tt)*) => {
245        $crate::log!($crate::protocol::base::Severity::Error, $($args)*);
246    };
247}
248
249/// Logs a fatal-level message.
250///
251/// Fatal messages indicate critical errors that will likely cause
252/// the program to terminate or become unusable.
253///
254/// # Examples
255///
256/// Simple fatal message:
257/// ```rust
258/// use veecle_telemetry::fatal;
259///
260/// fatal!("Critical system failure");
261/// ```
262///
263/// Fatal error with context:
264/// ```rust
265/// use veecle_telemetry::fatal;
266///
267/// let component = "memory_allocator";
268/// let error_type = "out_of_memory";
269/// fatal!(
270///     "System component failure",
271///     component = component,
272///     error_type = error_type,
273///     "available_memory_mb" = 0
274/// );
275/// ```
276#[macro_export]
277macro_rules! fatal {
278    ($($args:tt)*) => {
279        $crate::log!($crate::protocol::base::Severity::Fatal, $($args)*);
280    };
281}
282
283/// Constructs a slice of `KeyValue` attributes.
284///
285/// This macro is primarily used when manually constructing spans.
286///
287/// # Syntax
288///
289/// The macro supports several attribute formats:
290/// - `identifier = value` - Uses the identifier as the key name
291/// - `"literal" = value` - Uses the literal string as the key name
292/// - `identifier` - Uses the identifier as both key and value
293/// - `field.subfield` - Simple dot notation for field access
294///
295/// # Examples
296///
297/// Basic usage with mixed attribute types:
298/// ```rust
299/// use veecle_telemetry::attributes;
300///
301/// let user_id = 123;
302/// let service_name = "auth-service";
303/// let attrs = attributes!(user_id = user_id, "service" = service_name, "version" = "1.0.0");
304/// ```
305///
306/// Using identifiers as both key and value:
307/// ```rust
308/// use veecle_telemetry::attributes;
309///
310/// let database = "postgresql";
311/// let timeout = 30;
312/// let attrs = attributes!(
313///     database, // equivalent to database = database
314///     timeout = timeout,
315///     "connection_pool" = "primary"
316/// );
317/// ```
318///
319/// Span construction with attributes:
320/// ```rust
321/// use veecle_telemetry::{Span, attributes};
322///
323/// let operation = "user_login";
324/// let user_id = 456;
325/// let span = Span::new(
326///     "authentication",
327///     attributes!(operation = operation, user_id = user_id, "security_level" = "high"),
328/// );
329/// ```
330///
331/// Empty attributes:
332/// ```rust
333/// use veecle_telemetry::attributes;
334/// use veecle_telemetry::protocol::transient::KeyValue;
335///
336/// let attrs: &[KeyValue<'_>] = attributes!(); // Creates an empty slice
337/// ```
338#[macro_export]
339macro_rules! attributes {
340    ({ $($kvs:tt)* }) => {
341        $crate::attributes_inner!(@ { }, { $($kvs)* })
342    };
343    ($($kvs:tt)*) => {
344        $crate::attributes_inner!(@ { }, { $($kvs)* })
345    };
346}
347
348/// The actual implementation of `attributes!`, separated out to avoid accidentally recursing into
349/// the `$($tt)*` case from the inner cases.
350#[doc(hidden)]
351#[macro_export]
352macro_rules! attributes_inner {
353    // Base case, remaining tokens is empty.
354    (@ { $($val:expr,)* }, { } ) => {
355        &[ $($val,)* ]
356    };
357
358    // Recursive cases, take one key-value pair, add it to the output, and recurse on the remaining
359    // tokens.
360    (@ { $($out:expr,)* }, { $($key:ident).+ $(, $($rest:tt)*)? }) => {
361        $crate::attributes_inner!(
362            @ { $($out,)* $crate::attribute!($($key).+), },
363            { $($($rest)*)? }
364        )
365    };
366    (@ { $($out:expr,)* }, { $key:ident = $value:expr $(, $($rest:tt)*)? }) => {
367        $crate::attributes_inner!(
368            @ { $($out,)* $crate::attribute!($key = $value), },
369            { $($($rest)*)? }
370        )
371    };
372    (@ { $($out:expr,)* }, { $key:literal = $value:expr $(, $($rest:tt)*)? }) => {
373        $crate::attributes_inner!(
374            @ { $($out,)* $crate::attribute!($key = $value), },
375            { $($($rest)*)? }
376        )
377    };
378}
379
380/// Constructs a single attribute `KeyValue` pair.
381#[macro_export]
382macro_rules! attribute {
383    ($($key:ident)+ = $value:expr) => {
384        $crate::protocol::transient::KeyValue::new(::core::stringify!($($key).+), &$value)
385    };
386    ($key:literal = $value:expr) => {
387        $crate::protocol::transient::KeyValue::new($key, &$value)
388    };
389    ($($key:ident)+) => {
390        $crate::protocol::transient::KeyValue::new(::core::stringify!($($key).+), &$($key).+)
391    };
392}