refactor(folder): remove workspace debug logging from aux panels

This commit is contained in:
xintaofei
2026-04-14 22:39:57 +08:00
parent b5e8fd8acb
commit 0557eab154
3 changed files with 5 additions and 240 deletions

View File

@@ -94,7 +94,6 @@ function baseName(path: string): string {
const FILE_TREE_ROOT_PATH = "__workspace_root__" const FILE_TREE_ROOT_PATH = "__workspace_root__"
const GITIGNORE_MUTED_CLASS = "text-muted-foreground/55" const GITIGNORE_MUTED_CLASS = "text-muted-foreground/55"
const FILE_TREE_LAZY_DEBUG_LOG = process.env.NODE_ENV === "development"
interface FileActionTarget { interface FileActionTarget {
kind: "file" | "dir" kind: "file" | "dir"
@@ -129,30 +128,6 @@ function normalizeComparePath(path: string): string {
return path.replace(/\\/g, "/").replace(/\/+$/, "") return path.replace(/\\/g, "/").replace(/\/+$/, "")
} }
function logFileTreeLazyDebug(
message: string,
payload?: Record<string, unknown>
) {
if (!FILE_TREE_LAZY_DEBUG_LOG) return
if (payload) {
console.info(`[FileTreeTab/lazy] ${message}`, payload)
return
}
console.info(`[FileTreeTab/lazy] ${message}`)
}
function logFileTreeWorkspaceDebug(
message: string,
payload?: Record<string, unknown>
) {
if (!FILE_TREE_LAZY_DEBUG_LOG) return
if (payload) {
console.info(`[FileTreeTab/workspace] ${message}`, payload)
return
}
console.info(`[FileTreeTab/workspace] ${message}`)
}
function prefixFileTreeNodePaths( function prefixFileTreeNodePaths(
nodes: FileTreeNode[], nodes: FileTreeNode[],
prefix: string prefix: string
@@ -1013,15 +988,6 @@ export function FileTreeTab() {
workspaceState.health === "resyncing" && workspaceState.seq === 0 workspaceState.health === "resyncing" && workspaceState.seq === 0
) )
setError(workspaceState.health === "degraded" ? workspaceState.error : null) setError(workspaceState.health === "degraded" ? workspaceState.error : null)
logFileTreeWorkspaceDebug("workspace state consumed", {
rootPath: folder?.path ?? "",
seq: workspaceState.seq,
health: workspaceState.health,
treeRoots: workspaceState.tree.length,
gitEntries: workspaceState.git.length,
lazyOverrideDirs: lazyLoadedChildrenByPathRef.current.size,
})
}, [ }, [
folder?.path, folder?.path,
workspaceState.error, workspaceState.error,
@@ -1037,20 +1003,8 @@ export function FileTreeTab() {
if (!rootPath) return if (!rootPath) return
const normalizedDirPath = normalizeComparePath(dirPath) const normalizedDirPath = normalizeComparePath(dirPath)
if (!normalizedDirPath) return if (!normalizedDirPath) return
if (lazyLoadedChildrenByPathRef.current.has(normalizedDirPath)) { if (lazyLoadedChildrenByPathRef.current.has(normalizedDirPath)) return
logFileTreeLazyDebug("skip cached", { if (lazyLoadingDirPathsRef.current.has(normalizedDirPath)) return
rootPath,
dirPath: normalizedDirPath,
})
return
}
if (lazyLoadingDirPathsRef.current.has(normalizedDirPath)) {
logFileTreeLazyDebug("skip in-flight", {
rootPath,
dirPath: normalizedDirPath,
})
return
}
const existingChildren = findDirectoryChildren(nodes, normalizedDirPath) const existingChildren = findDirectoryChildren(nodes, normalizedDirPath)
if (existingChildren && existingChildren.length > 0) { if (existingChildren && existingChildren.length > 0) {
@@ -1058,20 +1012,10 @@ export function FileTreeTab() {
normalizedDirPath, normalizedDirPath,
existingChildren existingChildren
) )
logFileTreeLazyDebug("skip use existing children", {
rootPath,
dirPath: normalizedDirPath,
childrenCount: existingChildren.length,
})
return return
} }
lazyLoadingDirPathsRef.current.add(normalizedDirPath) lazyLoadingDirPathsRef.current.add(normalizedDirPath)
const startedAt = performance.now()
logFileTreeLazyDebug("request start", {
rootPath,
dirPath: normalizedDirPath,
})
try { try {
const subtree = await getFileTree( const subtree = await getFileTree(
joinFsPath(rootPath, normalizedDirPath), joinFsPath(rootPath, normalizedDirPath),
@@ -1082,19 +1026,8 @@ export function FileTreeTab() {
setNodes((prev) => setNodes((prev) =>
applyLazyTreeOverrides(prev, lazyLoadedChildrenByPathRef.current) applyLazyTreeOverrides(prev, lazyLoadedChildrenByPathRef.current)
) )
logFileTreeLazyDebug("request success", {
rootPath,
dirPath: normalizedDirPath,
childrenCount: prefixed.length,
durationMs: Math.round(performance.now() - startedAt),
})
} catch { } catch {
// Ignore lazy load failures and keep current collapsed/empty state. // Ignore lazy load failures and keep current collapsed/empty state.
logFileTreeLazyDebug("request failed", {
rootPath,
dirPath: normalizedDirPath,
durationMs: Math.round(performance.now() - startedAt),
})
} finally { } finally {
lazyLoadingDirPathsRef.current.delete(normalizedDirPath) lazyLoadingDirPathsRef.current.delete(normalizedDirPath)
} }
@@ -1107,10 +1040,6 @@ export function FileTreeTab() {
for (const path of expandedPaths) { for (const path of expandedPaths) {
if (path === FILE_TREE_ROOT_PATH) continue if (path === FILE_TREE_ROOT_PATH) continue
if (previousExpanded.has(path)) continue if (previousExpanded.has(path)) continue
logFileTreeLazyDebug("expanded path detected", {
rootPath: folder?.path ?? "",
dirPath: path,
})
void loadDirectoryChildren(path) void loadDirectoryChildren(path)
} }
previousExpandedPathsRef.current = new Set(expandedPaths) previousExpandedPathsRef.current = new Set(expandedPaths)

View File

@@ -115,19 +115,6 @@ interface MutableChangeTreeDirNode {
const TRACKED_ROOT_PATH = "__working_tree_tracked_root__" const TRACKED_ROOT_PATH = "__working_tree_tracked_root__"
const UNTRACKED_ROOT_PATH = "__working_tree_untracked_root__" const UNTRACKED_ROOT_PATH = "__working_tree_untracked_root__"
const UNTRACKED_STATUS = "??" const UNTRACKED_STATUS = "??"
const GIT_CHANGES_DEBUG_LOG = process.env.NODE_ENV === "development"
function logGitChangesDebug(
message: string,
payload?: Record<string, unknown>
) {
if (!GIT_CHANGES_DEBUG_LOG) return
if (payload) {
console.info(`[GitChangesTab/workspace] ${message}`, payload)
return
}
console.info(`[GitChangesTab/workspace] ${message}`)
}
type GitFileState = type GitFileState =
| "untracked" | "untracked"
@@ -545,24 +532,6 @@ export function GitChangesTab() {
[expandedUntrackedPaths.size, untrackedTreeNodes.length] [expandedUntrackedPaths.size, untrackedTreeNodes.length]
) )
useEffect(() => {
logGitChangesDebug("workspace state consumed", {
rootPath: folder?.path ?? "",
seq: workspaceState.seq,
health: workspaceState.health,
gitEntries: workspaceState.git.length,
trackedChanges: trackedChanges.length,
untrackedChanges: untrackedChanges.length,
})
}, [
folder?.path,
trackedChanges.length,
untrackedChanges.length,
workspaceState.git.length,
workspaceState.health,
workspaceState.seq,
])
const toggleTrackedExpanded = useCallback(() => { const toggleTrackedExpanded = useCallback(() => {
if (trackedCanExpand) { if (trackedCanExpand) {
setExpandedTrackedPaths(new Set(allTrackedDirectoryPaths)) setExpandedTrackedPaths(new Set(allTrackedDirectoryPaths))

View File

@@ -35,7 +35,6 @@ export interface WorkspaceStateResult extends WorkspaceStateView {
const WORKSPACE_PROTOCOL_VERSION = 1 const WORKSPACE_PROTOCOL_VERSION = 1
const STORE_EVICT_DELAY_MS = 120_000 const STORE_EVICT_DELAY_MS = 120_000
const STORE_SHUTDOWN_GRACE_MS = 600 const STORE_SHUTDOWN_GRACE_MS = 600
const WORKSPACE_DEBUG_LOG = process.env.NODE_ENV === "development"
const EMPTY_STATE: WorkspaceStateView = { const EMPTY_STATE: WorkspaceStateView = {
rootPath: "", rootPath: "",
@@ -56,38 +55,6 @@ function toErrorMessage(error: unknown): string {
return String(error) return String(error)
} }
function logWorkspaceDebug(message: string, payload?: Record<string, unknown>) {
if (!WORKSPACE_DEBUG_LOG) return
if (payload) {
console.info(`[WorkspaceStateStore] ${message}`, payload)
return
}
console.info(`[WorkspaceStateStore] ${message}`)
}
function summarizeSnapshot(snapshot: WorkspaceSnapshotResponse) {
return {
rootPath: snapshot.root_path,
seq: snapshot.seq,
full: snapshot.full,
deltas: snapshot.deltas.length,
treeRoots: snapshot.tree_snapshot?.length ?? 0,
gitEntries: snapshot.git_snapshot?.length ?? 0,
}
}
function summarizeEvent(event: WorkspaceStateEvent, localSeq: number) {
return {
rootPath: event.root_path,
kind: event.kind,
eventSeq: event.seq,
localSeq,
requiresResync: event.requires_resync,
payloadKinds: event.payload.map((delta) => delta.kind),
payloadCount: event.payload.length,
}
}
function applyDeltaToState( function applyDeltaToState(
state: WorkspaceStateView, state: WorkspaceStateView,
delta: WorkspaceDelta delta: WorkspaceDelta
@@ -198,11 +165,6 @@ class WorkspaceStateStore {
this.cancelPendingShutdown() this.cancelPendingShutdown()
this.cancelEviction() this.cancelEviction()
this.refCount += 1 this.refCount += 1
logWorkspaceDebug("acquire", {
rootPath: this.rootPath,
refCount: this.refCount,
started: this.started,
})
if (this.refCount === 1) { if (this.refCount === 1) {
const canReuseLifecycle = const canReuseLifecycle =
this.lifecycleId > 0 && this.lifecycleId > 0 &&
@@ -218,11 +180,6 @@ class WorkspaceStateStore {
release = () => { release = () => {
if (this.refCount === 0) return if (this.refCount === 0) return
this.refCount -= 1 this.refCount -= 1
logWorkspaceDebug("release", {
rootPath: this.rootPath,
refCount: this.refCount,
started: this.started,
})
if (this.refCount === 0) { if (this.refCount === 0) {
const lifecycleId = this.lifecycleId const lifecycleId = this.lifecycleId
this.scheduleShutdown(lifecycleId) this.scheduleShutdown(lifecycleId)
@@ -231,16 +188,9 @@ class WorkspaceStateStore {
requestResync = async (reason?: string) => { requestResync = async (reason?: string) => {
void reason void reason
if (this.resyncInFlight) { if (this.resyncInFlight) return this.resyncInFlight
logWorkspaceDebug("requestResync skip in-flight", {
rootPath: this.rootPath,
reason: reason ?? "unknown",
})
return this.resyncInFlight
}
const run = async () => { const run = async () => {
const startedAt = performance.now()
this.patchState((prev) => ({ this.patchState((prev) => ({
...prev, ...prev,
health: "resyncing", health: "resyncing",
@@ -248,33 +198,17 @@ class WorkspaceStateStore {
try { try {
const sinceSeq = this.hasBaselineSnapshot ? this.state.seq : undefined const sinceSeq = this.hasBaselineSnapshot ? this.state.seq : undefined
logWorkspaceDebug("requestResync start", {
rootPath: this.rootPath,
reason: reason ?? "unknown",
sinceSeq: sinceSeq ?? null,
})
const snapshot = await getWorkspaceSnapshot(this.rootPath, sinceSeq) const snapshot = await getWorkspaceSnapshot(this.rootPath, sinceSeq)
this.patchState((prev) => applySnapshot(prev, snapshot)) this.patchState((prev) => applySnapshot(prev, snapshot))
if (snapshot.full) { if (snapshot.full) {
this.hasBaselineSnapshot = true this.hasBaselineSnapshot = true
} }
logWorkspaceDebug("requestResync success", {
...summarizeSnapshot(snapshot),
reason: reason ?? "unknown",
durationMs: Math.round(performance.now() - startedAt),
})
} catch (error) { } catch (error) {
this.patchState((prev) => ({ this.patchState((prev) => ({
...prev, ...prev,
health: "degraded", health: "degraded",
error: toErrorMessage(error), error: toErrorMessage(error),
})) }))
logWorkspaceDebug("requestResync failed", {
rootPath: this.rootPath,
reason: reason ?? "unknown",
durationMs: Math.round(performance.now() - startedAt),
error: toErrorMessage(error),
})
} }
} }
@@ -305,27 +239,13 @@ class WorkspaceStateStore {
} }
try { try {
const streamStartedAt = performance.now()
logWorkspaceDebug("ensureStarted start stream", {
rootPath: this.rootPath,
lifecycleId,
})
const initialSnapshot = await startWorkspaceStateStream(this.rootPath) const initialSnapshot = await startWorkspaceStateStream(this.rootPath)
if (!this.isLifecycleActive(lifecycleId)) { if (!this.isLifecycleActive(lifecycleId)) {
await stopWorkspaceStateStream(this.rootPath).catch(() => {}) await stopWorkspaceStateStream(this.rootPath).catch(() => {})
logWorkspaceDebug("ensureStarted aborted after initial snapshot", {
rootPath: this.rootPath,
lifecycleId,
})
return return
} }
this.patchState((prev) => applySnapshot(prev, initialSnapshot)) this.patchState((prev) => applySnapshot(prev, initialSnapshot))
this.hasBaselineSnapshot = true this.hasBaselineSnapshot = true
logWorkspaceDebug("ensureStarted initial snapshot", {
...summarizeSnapshot(initialSnapshot),
lifecycleId,
durationMs: Math.round(performance.now() - streamStartedAt),
})
const unlisten = await subscribe<WorkspaceStateEvent>( const unlisten = await subscribe<WorkspaceStateEvent>(
"folder://workspace-state-event", "folder://workspace-state-event",
@@ -338,10 +258,6 @@ class WorkspaceStateStore {
this.handleEvent(event) this.handleEvent(event)
} }
) )
logWorkspaceDebug("ensureStarted subscribe ready", {
rootPath: this.rootPath,
lifecycleId,
})
if (!this.isLifecycleActive(lifecycleId)) { if (!this.isLifecycleActive(lifecycleId)) {
unlisten() unlisten()
@@ -351,35 +267,18 @@ class WorkspaceStateStore {
this.unlisten = unlisten this.unlisten = unlisten
this.started = true this.started = true
const catchUpStartedAt = performance.now()
const catchUpSnapshot = await getWorkspaceSnapshot( const catchUpSnapshot = await getWorkspaceSnapshot(
this.rootPath, this.rootPath,
this.state.seq this.state.seq
) )
if (!this.isLifecycleActive(lifecycleId)) { if (!this.isLifecycleActive(lifecycleId)) return
logWorkspaceDebug("ensureStarted aborted after catch-up snapshot", {
rootPath: this.rootPath,
lifecycleId,
})
return
}
this.patchState((prev) => applySnapshot(prev, catchUpSnapshot)) this.patchState((prev) => applySnapshot(prev, catchUpSnapshot))
logWorkspaceDebug("ensureStarted catch-up snapshot", {
...summarizeSnapshot(catchUpSnapshot),
lifecycleId,
durationMs: Math.round(performance.now() - catchUpStartedAt),
})
} catch (error) { } catch (error) {
this.patchState((prev) => ({ this.patchState((prev) => ({
...prev, ...prev,
health: "degraded", health: "degraded",
error: toErrorMessage(error), error: toErrorMessage(error),
})) }))
logWorkspaceDebug("ensureStarted failed", {
rootPath: this.rootPath,
lifecycleId,
error: toErrorMessage(error),
})
} }
} }
@@ -393,10 +292,6 @@ class WorkspaceStateStore {
private shutdown = async (lifecycleId: number) => { private shutdown = async (lifecycleId: number) => {
void lifecycleId void lifecycleId
this.started = false this.started = false
logWorkspaceDebug("shutdown", {
rootPath: this.rootPath,
lifecycleId,
})
const unlisten = this.unlisten const unlisten = this.unlisten
this.unlisten = null this.unlisten = null
if (unlisten) { if (unlisten) {
@@ -415,14 +310,7 @@ class WorkspaceStateStore {
this.cancelPendingShutdown() this.cancelPendingShutdown()
this.shutdownTimer = setTimeout(() => { this.shutdownTimer = setTimeout(() => {
this.shutdownTimer = null this.shutdownTimer = null
if (this.refCount !== 0) { if (this.refCount !== 0) return
logWorkspaceDebug("shutdown grace canceled by new acquire", {
rootPath: this.rootPath,
lifecycleId,
refCount: this.refCount,
})
return
}
const dispose = async () => { const dispose = async () => {
await this.shutdown(lifecycleId) await this.shutdown(lifecycleId)
} }
@@ -465,26 +353,12 @@ class WorkspaceStateStore {
} }
private handleEvent = (event: WorkspaceStateEvent) => { private handleEvent = (event: WorkspaceStateEvent) => {
logWorkspaceDebug("event received", summarizeEvent(event, this.state.seq))
if (event.version !== WORKSPACE_PROTOCOL_VERSION) { if (event.version !== WORKSPACE_PROTOCOL_VERSION) {
logWorkspaceDebug("event version mismatch", {
rootPath: this.rootPath,
eventVersion: event.version,
expectedVersion: WORKSPACE_PROTOCOL_VERSION,
})
void this.requestResync("version_mismatch") void this.requestResync("version_mismatch")
return return
} }
if (event.requires_resync || event.seq !== this.state.seq + 1) { if (event.requires_resync || event.seq !== this.state.seq + 1) {
logWorkspaceDebug("event requires resync", {
rootPath: this.rootPath,
kind: event.kind,
eventSeq: event.seq,
localSeq: this.state.seq,
requiresResync: event.requires_resync,
})
void this.requestResync("seq_gap_or_hint") void this.requestResync("seq_gap_or_hint")
return return
} }
@@ -502,13 +376,6 @@ class WorkspaceStateStore {
health: "healthy", health: "healthy",
error: null, error: null,
})) }))
logWorkspaceDebug("event applied", {
rootPath: event.root_path,
seq: event.seq,
treeRoots: next.tree.length,
gitEntries: next.git.length,
})
} }
private patchState = ( private patchState = (