Skip to main content

DevelopmentNodeEnvironment_MicrosoftVSCodeDependency_22NodeVersion_Bundle_Clean_Debug_ElectronProfile_EsbuildCompiler_Mountain/IPC/DevLog/
mod.rs

1//! # DevLog - Tag-filtered development logging
2//!
3//! Tag-gated logging used across Mountain. Controlled by the
4//! `Trace` env var: `Trace=vfs,ipc` for selective tags,
5//! `Trace=all` for everything, `Trace=short` for the
6//! everything-but-firehose preset (path aliasing + dedupe).
7//! Mirror to a session log file when `Record=1` (or when
8//! `Trace` is set in a debug build).
9//!
10//! Layout: every public Fn/Struct lives in its own sibling
11//! file. The two macros (`dev_log!`, `otel_span!`) live here
12//! so `#[macro_export]` puts them at the crate root and the
13//! callsite spelling stays `dev_log!("ipc", "…")`.
14
15pub mod AliasPath;
16
17pub mod AppDataPrefix;
18
19pub mod DebugOnce;
20
21pub mod DedupState;
22
23pub mod EmitOTLPSpan;
24
25pub mod FlushDedup;
26
27pub mod InitEager;
28
29pub mod IsBenignEnoent;
30
31pub mod IsEnabled;
32
33pub mod IsShort;
34
35pub mod NowNano;
36
37pub mod SessionTimestamp;
38
39pub mod WriteToFile;
40
41/// Tag-gated dev log. Compiled out in release builds.
42///
43/// Under `Trace=short` aliases the long Tauri app-data prefix
44/// to `$APP` and collapses consecutive duplicates with a
45/// `(xN)` tail. The body is fully gated on
46/// `cfg!(debug_assertions)` so release builds get zero runtime
47/// cost (LLVM dead-codes the format / IsEnabled / file-sink
48/// path).
49#[macro_export]
50macro_rules! dev_log {
51
52	($Tag:expr, $($Arg:tt)*) => {
53
54		if cfg!(debug_assertions) && $crate::IPC::DevLog::IsEnabled::Fn($Tag) {
55
56			let RawMessage = format!($($Arg)*);
57
58			let TagUpper = $Tag.to_uppercase();
59
60			if $crate::IPC::DevLog::IsShort::Fn() {
61
62				let Aliased = $crate::IPC::DevLog::AliasPath::Fn(&RawMessage);
63
64				let Key = format!("{}:{}", TagUpper, Aliased);
65
66				let ShouldPrint = {
67
68					if let Ok(mut State) = $crate::IPC::DevLog::DedupState::DEDUP.lock() {
69
70						if State.LastKey == Key {
71
72							State.Count += 1;
73
74							false
75						} else {
76
77							let PrevCount = State.Count;
78
79							let HadPrev = !State.LastKey.is_empty();
80
81							State.LastKey = Key;
82
83							State.Count = 1;
84
85							if HadPrev && PrevCount > 1 {
86
87								let Tail = format!("  (x{})", PrevCount);
88
89								eprintln!("{}", Tail);
90
91								$crate::IPC::DevLog::WriteToFile::Fn(&Tail);
92							}
93
94							true
95						}
96					} else {
97
98						true
99					}
100				};
101
102				if ShouldPrint {
103
104					let Formatted = format!("[DEV:{}] {}", TagUpper, Aliased);
105
106					eprintln!("{}", Formatted);
107
108					$crate::IPC::DevLog::WriteToFile::Fn(&Formatted);
109				}
110			} else {
111
112				let Formatted = format!("[DEV:{}] {}", TagUpper, RawMessage);
113
114				eprintln!("{}", Formatted);
115
116				$crate::IPC::DevLog::WriteToFile::Fn(&Formatted);
117			}
118		}
119	};
120}
121
122/// Convenience macro: emit an OTLP span for an IPC handler.
123/// Usage: `otel_span!("file:readFile", StartNano, &[("path", &Path)]);`
124#[macro_export]
125macro_rules! otel_span {
126	($Name:expr, $Start:expr, $Attrs:expr) => {
127		$crate::IPC::DevLog::EmitOTLPSpan::Fn($Name, $Start, $crate::IPC::DevLog::NowNano::Fn(), $Attrs)
128	};
129
130	($Name:expr, $Start:expr) => {
131		$crate::IPC::DevLog::EmitOTLPSpan::Fn($Name, $Start, $crate::IPC::DevLog::NowNano::Fn(), &[])
132	};
133}