Skip to main content

Vine/
DevLog.rs

1//! # Vine::DevLog
2//!
3//! Tag-gated, debug-only logging macro. Gates on `cfg!(debug_assertions)`
4//! and the `LAND_DEV_LOG` environment variable, then emits through the
5//! `log` crate so the embedder's configured logger (Air's `env_logger`,
6//! Mountain's tracing layer, …) decides where it lands.
7//!
8//! ## Usage
9//!
10//! ```ignore
11//! use Vine::dev_log;
12//!
13//! dev_log!("grpc", "Connecting to sidecar '{}' at '{}'", id, addr);
14//! ```
15//!
16//! ## Tag filter
17//!
18//! `LAND_DEV_LOG` accepts:
19//! - unset / empty - no dev-log output (release default).
20//! - `all` - every tag emits.
21//! - comma-separated tags (e.g. `LAND_DEV_LOG=grpc,vine,boot`) - only the
22//!   listed tags emit.
23//!
24//! The check is `O(1)` for `all` and `O(tag-count)` for the list form.
25//! Release builds short-circuit at the `cfg!(debug_assertions)` gate so the
26//! environment read never executes.
27
28/// Monotonic process-relative nanosecond timestamp.
29///
30/// Used by Vine notification fan-out to stamp every frame without paying for
31/// a `SystemTime::now()` syscall per call.
32pub fn NowNano() -> u64 {
33	use std::time::Instant;
34
35	static START:once_cell::sync::Lazy<Instant> = once_cell::sync::Lazy::new(Instant::now);
36
37	START.elapsed().as_nanos() as u64
38}
39
40/// Returns `true` when dev-log emission is enabled for `Tag`.
41///
42/// Reads `LAND_DEV_LOG` on every call. Cheap in practice (single
43/// `std::env::var` lookup) and avoids the cache-invalidation problem that a
44/// `OnceLock`-backed parse would create when the environment changes after
45/// boot (e.g. tests that flip the variable per-case).
46pub fn IsEnabled(Tag:&str) -> bool {
47	let Filter = match std::env::var("LAND_DEV_LOG") {
48		Ok(Value) => Value,
49
50		Err(_) => return false,
51	};
52
53	if Filter.is_empty() {
54		return false;
55	}
56
57	if Filter == "all" || Filter == "1" || Filter == "true" {
58		return true;
59	}
60
61	Filter.split(',').any(|Entry| Entry.trim().eq_ignore_ascii_case(Tag))
62}
63
64/// Tag-gated dev log. Compiled out in release builds via
65/// `cfg!(debug_assertions)` short-circuit.
66///
67/// The body of the macro lives in this crate's `log` crate facade so the
68/// embedder's logger decides routing. Mountain's tracing subscriber + Air's
69/// `env_logger` both pick this up automatically without further wiring.
70#[macro_export]
71macro_rules! dev_log {
72
73	($Tag:expr, $($Arg:tt)*) => {{
74		if cfg!(debug_assertions) && $crate::DevLog::IsEnabled($Tag) {
75			let Message = format!($($Arg)*);
76
77			::log::debug!(target: $Tag, "{}", Message);
78		}
79	}};
80}