Add `DEBUG_FSR` flag for conditional partial FileSystemRouter logging

pull/373/head
Kelvin Schoofs 2 years ago
parent 76a28be0f2
commit 7d59992b92

@ -11,6 +11,10 @@
- Added the `DEBUG_FS` flag to allow enabling detailed conditional logging in `sshFileSystem` (#341) - Added the `DEBUG_FS` flag to allow enabling detailed conditional logging in `sshFileSystem` (#341)
- This flag will auto-update when it changes in global flags, unless it's overriden in your SSH FS config - This flag will auto-update when it changes in global flags, unless it's overriden in your SSH FS config
- Mostly meant for internal debugging or helping with debugging specific user-reported issues - Mostly meant for internal debugging or helping with debugging specific user-reported issues
- Added the `DEBUG_FSR` flag to allow enabing detailed conditional logging for the `FileSystemRouter`
- Similar to `DEBUG_FS` this is mostly meant for internal debugging or when useful for user-reported issues
- This flag will also auto-update when it changes in global flags.
- This is a singleton flag and thus unaffected by overriding it in your SSH FS configs
## v1.25.0 (2022-06-01) ## v1.25.0 (2022-06-01)

@ -5,7 +5,7 @@ import { parse as parseJsonc, ParseError } from 'jsonc-parser';
import * as semver from 'semver'; import * as semver from 'semver';
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import { Logging } from './logging'; import { Logging } from './logging';
import { toPromise } from './utils'; import { catchingPromise, toPromise } from './utils';
// Logger scope with default warning/error options (which enables stacktraces) disabled // Logger scope with default warning/error options (which enables stacktraces) disabled
const logging = Logging.scope(undefined, false); const logging = Logging.scope(undefined, false);
@ -394,6 +394,10 @@ function parseFlagList(list: string[] | undefined, origin: string): Record<strin
- The presence of `missing` will log `FileNotFound` errors in `minimal` and `full` (except `ignoredmissing` ones) - The presence of `missing` will log `FileNotFound` errors in `minimal` and `full` (except `ignoredmissing` ones)
- The presence of `converted` will log the resulting converted errors (if required and successful) - The presence of `converted` will log the resulting converted errors (if required and successful)
- The presence of `all` enables all of the above (similar to `ignoredmissing,full,missing,converted,reads`) - The presence of `all` enables all of the above (similar to `ignoredmissing,full,missing,converted,reads`)
DEBUG_FSR (string) (default='', global)
- A comma-separated list of method names to enable logging for in the FileSystemRouter
- The presence of `all` is equal to `stat,readDirectory,createDirectory,readFile,writeFile,delete,rename`
- The router logs handles `ssh://`, and will even log operations to non-existing configurations/connections
FS_NOTIFY_ERRORS (boolean) (default=false) FS_NOTIFY_ERRORS (boolean) (default=false)
- Enables displaying error notifications when a file system operation fails and isn't automatically ignored - Enables displaying error notifications when a file system operation fails and isn't automatically ignored
- Automatically enabled VS Code 1.56 and later (see issue #282) - Automatically enabled VS Code 1.56 and later (see issue #282)
@ -430,6 +434,9 @@ function calculateFlags(): Record<string, FlagCombo> {
applyList(config.workspaceValue, 'Workspace Settings'); applyList(config.workspaceValue, 'Workspace Settings');
applyList(config.workspaceFolderValue, 'WorkspaceFolder Settings'); applyList(config.workspaceFolderValue, 'WorkspaceFolder Settings');
Logging.info`Calculated config flags: ${flags}`; Logging.info`Calculated config flags: ${flags}`;
for (const listener of globalFlagsSubscribers) {
catchingPromise(listener).catch(e => Logging.error`onGlobalFlagsChanged listener errored: ${e}`);
}
return cachedFlags = flags; return cachedFlags = flags;
} }

@ -1,12 +1,23 @@
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import { getFlag, subscribeToGlobalFlags } from './config';
import { Logging } from './logging'; import { Logging } from './logging';
import type { Manager } from './manager'; import type { Manager } from './manager';
const ALL_DEBUG_FLAGS = [
'stat', 'readDirectory', 'createDirectory',
'readFile', 'writeFile', 'delete', 'rename',
].map(v => v.toLowerCase());
export class FileSystemRouter implements vscode.FileSystemProvider { export class FileSystemRouter implements vscode.FileSystemProvider {
public onDidChangeFile: vscode.Event<vscode.FileChangeEvent[]>; public onDidChangeFile: vscode.Event<vscode.FileChangeEvent[]>;
protected onDidChangeFileEmitter = new vscode.EventEmitter<vscode.FileChangeEvent[]>(); protected onDidChangeFileEmitter = new vscode.EventEmitter<vscode.FileChangeEvent[]>();
protected debugFlags: string[];
constructor(protected readonly manager: Manager) { constructor(protected readonly manager: Manager) {
this.onDidChangeFile = this.onDidChangeFileEmitter.event; this.onDidChangeFile = this.onDidChangeFileEmitter.event;
subscribeToGlobalFlags(() => {
this.debugFlags = `${getFlag('DEBUG_FSR')?.[0] || ''}`.toLowerCase().split(/,\s*|\s+/g);
if (this.debugFlags.includes('all')) this.debugFlags.push(...ALL_DEBUG_FLAGS);
});
} }
public async assertFs(uri: vscode.Uri): Promise<vscode.FileSystemProvider> { public async assertFs(uri: vscode.Uri): Promise<vscode.FileSystemProvider> {
const fs = this.manager.getFs(uri); const fs = this.manager.getFs(uri);
@ -24,30 +35,41 @@ export class FileSystemRouter implements vscode.FileSystemProvider {
return new vscode.Disposable(() => { }); return new vscode.Disposable(() => { });
} }
public async stat(uri: vscode.Uri): Promise<vscode.FileStat> { public async stat(uri: vscode.Uri): Promise<vscode.FileStat> {
if (this.debugFlags.includes('stat'))
Logging.debug`Performing stat for ${uri}`;
return (await this.assertFs(uri)).stat(uri); return (await this.assertFs(uri)).stat(uri);
} }
public async readDirectory(uri: vscode.Uri): Promise<[string, vscode.FileType][]> { public async readDirectory(uri: vscode.Uri): Promise<[string, vscode.FileType][]> {
if (this.debugFlags.includes('readdirectory'))
Logging.debug`Reading directory ${uri}`;
return (await this.assertFs(uri)).readDirectory(uri); return (await this.assertFs(uri)).readDirectory(uri);
} }
public async createDirectory(uri: vscode.Uri): Promise<void> { public async createDirectory(uri: vscode.Uri): Promise<void> {
if (this.debugFlags.includes('createdirectory'))
Logging.debug`Creating directory ${uri}`;
return (await this.assertFs(uri)).createDirectory(uri); return (await this.assertFs(uri)).createDirectory(uri);
} }
public async readFile(uri: vscode.Uri): Promise<Uint8Array> { public async readFile(uri: vscode.Uri): Promise<Uint8Array> {
if (this.debugFlags.includes('readfile'))
Logging.debug`Reading ${uri}`; Logging.debug`Reading ${uri}`;
return (await this.assertFs(uri)).readFile(uri); return (await this.assertFs(uri)).readFile(uri);
} }
public async writeFile(uri: vscode.Uri, content: Uint8Array, options: { create: boolean; overwrite: boolean; }): Promise<void> { public async writeFile(uri: vscode.Uri, content: Uint8Array, options: { create: boolean; overwrite: boolean; }): Promise<void> {
Logging.debug`Writing ${content.length} bytes to ${uri}`; if (this.debugFlags.includes('writefile'))
Logging.debug`Writing ${content.length} bytes to ${uri} (options: ${options})`;
return (await this.assertFs(uri)).writeFile(uri, content, options); return (await this.assertFs(uri)).writeFile(uri, content, options);
} }
public async delete(uri: vscode.Uri, options: { recursive: boolean; }): Promise<void> { public async delete(uri: vscode.Uri, options: { recursive: boolean; }): Promise<void> {
Logging.debug`Deleting ${uri}`; if (this.debugFlags.includes('delete'))
Logging.debug`Deleting ${uri} (options: ${options})`;
return (await this.assertFs(uri)).delete(uri, options); return (await this.assertFs(uri)).delete(uri, options);
} }
public async rename(oldUri: vscode.Uri, newUri: vscode.Uri, options: { overwrite: boolean; }): Promise<void> { public async rename(oldUri: vscode.Uri, newUri: vscode.Uri, options: { overwrite: boolean; }): Promise<void> {
if (this.debugFlags.includes('rename'))
Logging.debug`Renaming ${oldUri} to ${newUri}`; Logging.debug`Renaming ${oldUri} to ${newUri}`;
const fs = await this.assertFs(oldUri); const fs = await this.assertFs(oldUri);
if (fs !== (await this.assertFs(newUri))) throw new Error(`Can't rename between different SSH filesystems`); if (fs !== (await this.assertFs(newUri)))
throw new Error(`Can't rename between different SSH filesystems`);
return fs.rename(oldUri, newUri, options); return fs.rename(oldUri, newUri, options);
} }
} }

Loading…
Cancel
Save