Skip to main content

vector_core/
macros.rs

1//! Log macros shared across all Vector clients.
2//!
3//! `log_info!`, `log_debug!`, `log_trace!` compile to no-ops in release builds.
4//! `log_warn!` always compiles in (with UTC timestamps). In ALL builds each
5//! macro is gated at runtime by the active level (see `crate::logging`): default
6//! WARN, override with `VECTOR_LOG=trace|debug|info|warn|error|off`. The level
7//! check is cheap and the message args aren't formatted when suppressed.
8
9// Release builds strip the info/debug/trace bodies entirely, so a variable
10// referenced only inside one of these macros would go unused. `keep_used!`
11// re-references the args in a dead `if false` block: DCE removes it (zero
12// runtime cost, args never evaluated) while the borrow checker still counts
13// the args as used, so call sites stay warning-free in every profile.
14#[macro_export]
15#[doc(hidden)]
16macro_rules! __log_keep_used {
17    ($($arg:tt)*) => {{
18        #[cfg(not(debug_assertions))]
19        if false { let _ = format_args!($($arg)*); }
20    }};
21}
22
23/// stderr natively; the browser console on wasm32, where stderr is a sink.
24#[macro_export]
25#[doc(hidden)]
26macro_rules! __log_line {
27    ($($arg:tt)*) => {{
28        #[cfg(not(target_arch = "wasm32"))]
29        eprintln!($($arg)*);
30        #[cfg(target_arch = "wasm32")]
31        $crate::logging::console_line(&format!($($arg)*));
32    }};
33}
34
35#[macro_export]
36macro_rules! log_info {
37    ($($arg:tt)*) => {{
38        #[cfg(debug_assertions)]
39        if $crate::logging::level_enabled($crate::logging::LEVEL_INFO) {
40            $crate::__log_line!("[INFO] {}", format_args!($($arg)*));
41        }
42        $crate::__log_keep_used!($($arg)*);
43    }};
44}
45
46#[macro_export]
47macro_rules! log_debug {
48    ($($arg:tt)*) => {{
49        #[cfg(debug_assertions)]
50        if $crate::logging::level_enabled($crate::logging::LEVEL_DEBUG) {
51            $crate::__log_line!("[DEBUG] {}", format_args!($($arg)*));
52        }
53        $crate::__log_keep_used!($($arg)*);
54    }};
55}
56
57#[macro_export]
58macro_rules! log_trace {
59    ($($arg:tt)*) => {{
60        #[cfg(debug_assertions)]
61        if $crate::logging::level_enabled($crate::logging::LEVEL_TRACE) {
62            $crate::__log_line!("[TRACE] {}", format_args!($($arg)*));
63        }
64        $crate::__log_keep_used!($($arg)*);
65    }};
66}
67
68#[macro_export]
69macro_rules! log_warn {
70    ($($arg:tt)*) => {{
71        if $crate::logging::level_enabled($crate::logging::LEVEL_WARN) {
72            let _secs = $crate::rt::time_std::SystemTime::now()
73                .duration_since($crate::rt::time_std::UNIX_EPOCH)
74                .unwrap_or_default()
75                .as_secs();
76            $crate::__log_line!("[WARN {:02}:{:02}:{:02}Z] {}", (_secs / 3600) % 24, (_secs / 60) % 60, _secs % 60, format_args!($($arg)*));
77        }
78    }};
79}
80
81/// Network-failure log: a WARN that ALSO lands in the app's persistent log
82/// (Settings > Copy Logs) via the registered sink — for upload/download/
83/// mirror failures the user may need to report long after the console
84/// scrolled away. No toast: fallbacks often succeed right after.
85#[macro_export]
86macro_rules! log_net_fail {
87    ($($arg:tt)*) => {{
88        let msg = format!($($arg)*);
89        // Console print matches log_warn! exactly (level-gated); persistence
90        // is unconditional — the log file exists for after-the-fact diagnosis.
91        if $crate::logging::level_enabled($crate::logging::LEVEL_WARN) {
92            $crate::__log_line!("[WARN] {}", &msg);
93        }
94        $crate::logging::persist(&format!(
95            "[{} WARN] {}",
96            $crate::logging::timestamp_utc(),
97            &msg
98        ));
99    }};
100}
101
102/// Network-milestone log: persisted like [`log_net_fail!`] but INFO-toned —
103/// which server won an upload, which fallback served a download, mirror
104/// results. Persisted even in release (where `log_info!` compiles out):
105/// the persistent log exists precisely for release-build diagnosis.
106#[macro_export]
107macro_rules! log_net_info {
108    ($($arg:tt)*) => {{
109        let msg = format!($($arg)*);
110        #[cfg(debug_assertions)]
111        if $crate::logging::level_enabled($crate::logging::LEVEL_INFO) {
112            $crate::__log_line!("[INFO] {}", &msg);
113        }
114        $crate::logging::persist(&format!(
115            "[{} INFO] {}",
116            $crate::logging::timestamp_utc(),
117            &msg
118        ));
119    }};
120}