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