Skip to main content

Module DevLog

Module DevLog 

Source
Expand description

Tag-filtered development logging (Trace env var). Must be declared before WindServiceHandlers so the dev_log! macro is available.

§DevLog - Tag-filtered development logging

Controlled by Trace environment variable. The same tags work in both Mountain (Rust) and Wind/Sky (TypeScript).

§Usage

Trace=vfs,ipc ./Mountain          # only VFS + IPC
Trace=all ./Mountain              # everything
Trace=short ./Mountain            # everything, compressed + deduped
Trace=terminal,exthost ./Mountain # terminal + extension host
./Mountain                               # nothing (only normal log!() output)

§Short Mode

Trace=short enables all tags but compresses output:

  • Long app-data paths aliased to $APP
  • Consecutive duplicate messages counted ((x14) suffix)
  • Rust log targets compressed (D::Binary::Main::EntryEntry)

§File sink

When Record=1 (or, in debug builds, Trace is set), every emitted line is mirrored to:

~/Library/Application Support/<bundle>/logs/<YYYYMMDDTHHMMSS>/Mountain.dev.log

The timestamp directory follows Tauri’s tauri-plugin-log format, so the dev log sits next to the plugin’s own log file for the same boot (one directory per process start). Use Record=0 to force- disable even in debug. File writes are flushed per line so tail -f shows live output.

§Tags (38 granular tags across all Elements)

TagScope
vfsFile stat, read, write, readdir, mkdir, delete, copy
ipcIPC routing: invoke dispatch, channel calls
configConfiguration get/set, env paths, workbench config
lifecycleStartup, shutdown, phases, window events
storageStorage get/set/delete, items, optimize
folderFolder picker, workspace navigation
exthostExtension host: create, start, kill, exit info
extensionsExtension scanning, activation, management
terminalTerminal/PTY: create, sendText, profiles, shell
searchSearch: findFiles, findInFiles
themesTheme: list, get active, set
windowWindow: focus, maximize, minimize, fullscreen
nativehostOS integration: process, devtools, shell
clipboardClipboard: read/write text, buffer, image
commandsCommand registry: execute, getAll
modelText model: open, close, get, updateContent
outputOutput channels: create, append, show
notificationNotifications: show, progress
progressProgress: begin, end, report
quickinputQuick input: showQuickPick, showInputBox
workingcopyWorking copy: dirty state
workspacesWorkspace: folders, recent, enter
keybindingKeybindings: add, remove, lookup
labelLabel service: getBase, getUri
historyNavigation history: push, goBack, goForward
decorationsDecorations: get, set, clear
textfileText file operations: read, write, save
updateUpdate service: check, download, apply
encryptionEncryption: encrypt, decrypt
menubarMenubar updates
urlURL handler: registerExternalUriOpener
grpcgRPC/Vine: server, client, connections
cocoonCocoon sidecar: spawn, health, handshake
bootstrapEffect-TS bootstrap stages
preloadPreload: globals, polyfills, ipcRenderer

§Batch 1 diagnostic tags (Row 1-3 fix surfaces)

Narrow tags added to isolate the architectural gaps surfaced by the analysis table. Enable selectively with e.g. Trace=notif-drop,git,tree-view to filter to just the subsystem under investigation.

TagScope
notif-dropNotifications that hit the _ => {} default arm (dropped silently)
provider-registerAccepted register_*_provider notifications + handle + extension id
channel-stubWind/Output TauriMainProcessService.call stub-hit vs route vs miss
gitlocalGit channel, GitExec RPC, SCM provider group updates
tree-viewtree.register, GetTreeChildren, sky://tree-view/create emit

§Batch 2 diagnostic tags

TagScope
sky-emitMountain → Wind/Sky sky:// emits: channel, payload bytes, ok/fail
config-primeConfiguration cache: manifest pre-populate, subtree synthesise
ext-activatePer-extension activate: start, outcome (ok/fail/skip), duration
breakerCocoon MountainClientService circuit-breaker state transitions
cel-dispatchSkyBridge cel:* CustomEvent dispatch + consumer-present flag

§Batch 3 diagnostic tags

Added 2026-04-23 late after Batches 3-6 wired notification handlers, git channel, tree-view dataProvider forwarding, and medium stub backfill. These tags catch the subsystems the new traffic passes through so regressions surface as silent tag counts going to zero (or, for tauri-invoke, per-invoke latency spikes).

TagScope
ext-scanExtension scanner decisions: is-builtin vs user, skip reasons, counts
scheme-assetsvscode-file:// / vscode-resource:// request routing, MIME, bytes
preload-shimWind Preload.ts globals wiring, VS Code ipcRenderer polyfill install
tauri-invokePer-invoke method + duration (augments ipc’s paired invoke/done lines)
bootstrap-stageCocoon Effect/Bootstrap.ts stage timings (start/ok/fail per phase)

§Batch 4 diagnostic tags

Added 2026-04-24 alongside the workspace.fs tier-split refactor. Cocoon’s WorkspaceNamespace/FileSystemRoute.ts now chooses between Tier A (node:fs/promises in-process) and Tier C (Mountain FileSystem.* gRPC) per URI scheme + custom-provider claim. The tag surfaces every decision so empirical workload profiling confirms the split is paying off - grep 'route=native' / grep 'route=mountain' buckets per run. Emitted from Cocoon stdout, picked up by Mountain’s [DEV:COCOON] stdout tail with the standard [DEV:FS-ROUTE] prefix.

TagScope
fs-routeworkspace.fs.* + openTextDocument native-vs-mountain routing
cmd-routecommands.executeCommand local-vs-mountain routing
dual-trackMountain-first / Node-fallback progressive Rust migration dispatches

§dual-track tag usage pattern

Every Cocoon shim that wraps TryMountainThenNode logs one of four decisions per dispatch:

  • route=mountain Mountain handled it (Rust code path served the call)
  • route=node-fallback Build-time manifest says no Mountain handler (or runtime confirmed “Unknown method: X”); Cocoon’s Node / stock-VS-Code implementation served it
  • route=unavailable Tier-4: no tier covers the method. Extension receives typed NotImplementedError; build surfaces this as a feature-gap
  • route=error Tier failed unexpectedly; error propagated

Grep the stream to see which vscode.* methods Mountain doesn’t yet cover - that set IS the Rust migration TODO list. A method moves from node-fallback to mountain automatically the moment Mountain lands its Rust handler AND the manifest is regenerated. route=unavailable rows are the apologise-to-user list.

A single [DEV:DUAL-TRACK] manifest mountain=N stockLift=M bespoke=K line prints at Cocoon boot with the build-time tier coverage generated by Maintain/Script/GenerateRouteManifest.sh.

Structs§

DedupState

Constants§

BENIGN_ENOENT_SUBSTRINGS 🔒
SHORT_MODE_MUTED_TAGS 🔒
Tags explicitly muted by short mode. These are the per-call firehose tags (receive / dispatch / verify / forward banners) that add no diagnostic signal beyond the aggregate IPC round-trip timing already present in the ipc / grpc summary lines. Listing them here keeps short usable as a “quiet but informative” default - the failure path for each of these still logs a specific error tag (grpc for gRPC errors, ipc for IPC failures, etc.).

Statics§

APP_DATA_PREFIX 🔒
DEBUG_ONCE_KEYS 🔒
DEDUP
ENABLED_TAGS 🔒
LOG_FILE 🔒
OTLP_AVAILABLE 🔒
OTLP_TRACE_ID 🔒
SHORT_MODE 🔒

Functions§

AliasPath
Replace the long app-data path with $APP in a string.
AppDataPrefix
Get the app-data path prefix for aliasing (cached).
BinarySignature 🔒
Produce an identity signature for THIS running binary derived from CARGO_PKG_NAME (which Maintain sets to the long PascalCase product name before cargo build). Each profile produces a distinct signature
DebugOnce
Emit the line exactly once per process, keyed on the supplied key. Later calls with the same key are silently dropped. The file sink still captures the very first occurrence so the probe is documented.
DebugOnceKeys 🔒
DetectAppDataPrefix 🔒
EmitOTLPSpan
Emit an OTLP span to the local collector (Jaeger at 127.0.0.1:4318). Fire-and-forget on a background thread. Stops trying after first failure.
EnabledTags 🔒
FileSinkEnabled 🔒
Decide whether the file sink should be active. Returns the final flag once per process; subsequent calls are cached.
FlushDedup
Flush the dedup buffer - prints the pending count if > 1.
FormatTimestamp 🔒
GetTraceId 🔒
InitEager
Force the file sink to initialize before any dev_log! has run.
InitFileSink 🔒
Initialise the file sink on first call. Silently falls through to a disabled sink if the directory or file can’t be created - the caller must never panic because of a log-file failure.
IsBenignEnoent
Return true when the given path is a known-optional probe whose absence is never an error condition. Used to downgrade stat ENOENT spam.
IsEnabled
Check if a tag is enabled.
IsShort
Whether Trace=short is active.
NowNano
ResolveLogDirectory 🔒
Resolve the log directory for this session: ~/Library/Application Support//logs//
SessionTimestamp
Session timestamp in local time, cached once per process. MUST match whatever WindServiceHandlers.rs::"nativeHost:getEnvironmentPaths" builds, because VS Code’s file service writes window1/output/*.log into the directory that handler returns - if DevLog and VS Code use different timezones, Mountain.dev.log and the window1/ subtree land in two sibling directories 2-3 hours apart, which makes every post-mortem investigation start with “which folder has the real log?”. Picking chrono::Local::now() matches the VS Code convention (Tauri’s tauri-plugin-log also writes local-time YYYYMMDDTHHMMSS).
SplitPascalCaseIntoWords 🔒
Split a PascalCase / UPPERCASE string into lowercase component words, matching the tokenisation Maintain’s Build/Process.rs applies when it stamps the Tauri identifier. Example: ElectronProfile["electron", "profile"]; 22NodeVersion["22", "node", "version"]. Empty segments are filtered out.
WriteToFile
Append a single formatted line to the session’s log file if the file sink is active. Swallows every error - dev_log must never crash.
rand_u64 🔒