Improve logging

feature/ssh-config
Kelvin Schoofs 4 years ago
parent 03fd60d36e
commit 107e22ec07

@ -29,6 +29,13 @@ export interface LoggingOptions {
* Defaults to 0 meaning no offset.
*/
callStacktraceOffset: number;
/** Used when the "message" to be logged is an Error object with a stack.
* 0: Don't output the stack
* -1: Output the whole stack
* N: Only output the first N lines
* The stack gets stringified in the first logger, so child loggers don't inherit, it uses the default (which is 0)
*/
maxErrorStack: number;
}
export const LOGGING_NO_STACKTRACE: Partial<LoggingOptions> = { callStacktrace: 0 };
@ -42,6 +49,7 @@ class Logger {
reportedFromLevel: 0,
callStacktrace: 0,
callStacktraceOffset: 0,
maxErrorStack: 0,
};
public overriddenTypeOptions: { [type in LoggerDefaultLevels]?: Partial<LoggingOptions> } = {
warning: { callStacktrace: 3, reportedFromLevel: 2 },
@ -79,15 +87,21 @@ class Logger {
}
protected print(type: string, message: string | Error, partialOptions?: Partial<LoggingOptions>) {
const options: LoggingOptions = { ...this.defaultLoggingOptions, ...this.overriddenTypeOptions[type], ...partialOptions };
// Format errors with stacktraces to display the stacktrace
// Format errors with stacktraces to display the JSON and the stacktrace if needed
if (message instanceof Error && message.stack) {
let json: string = '';
let msg = message.message;
try {
json = JSON.stringify(message);
} finally {
json = json ? `\nJSON: ${json}` : '';
message = `${message.message}${json}\n${message.stack}`;
msg += `\nJSON: ${JSON.stringify(message)}`;
} finally { }
const { maxErrorStack } = options;
if (message.stack && maxErrorStack) {
let { stack } = message;
if (maxErrorStack > 0) {
stack = stack.split(/\n/g).slice(0, maxErrorStack).join('\n');
}
msg += '\n' + stack;
}
message = msg;
}
// Do we need to also output a stacktrace?
const { callStacktrace, callStacktraceOffset = 0 } = options;

@ -6,7 +6,23 @@ import * as vscode from 'vscode';
import { FileSystemConfig } from './fileSystemConfig';
import { Logger, Logging, LOGGING_NO_STACKTRACE, LOGGING_SINGLE_LINE_STACKTRACE, withStacktraceOffset } from './logging';
const LOGGING_HANDLE_ERROR = withStacktraceOffset(1, LOGGING_SINGLE_LINE_STACKTRACE);
// This makes it report a single line of the stacktrace of where the e.g. logger.info() call happened
// while also making it that if we're logging an error, only the first 4 lines of the stack (including the error message) are shown
// (usually the errors we report on happen deep inside ssh2 or ssh2-streams, we don't really care that much about it)
const LOGGING_HANDLE_ERROR = withStacktraceOffset(1, { ...LOGGING_SINGLE_LINE_STACKTRACE, maxErrorStack: 4 });
// All absolute paths (relative to the FS root)
// If it ends with /, .startsWith is used, otherwise a raw equal
const IGNORE_NOT_FOUND: string[] = [
'/.vscode',
'/.vscode/',
'/.git/',
'/node_modules',
'/pom.xml',
];
function shouldIgnoreNotFound(path: string) {
return IGNORE_NOT_FOUND.some(entry => entry === path || entry.endsWith('/') && path.startsWith(entry));
}
export class SSHFileSystem implements vscode.FileSystemProvider {
public waitForContinue = false;
@ -142,6 +158,12 @@ export class SSHFileSystem implements vscode.FileSystemProvider {
}
// Helper function to handle/report errors with proper (and minimal) stacktraces and such
protected handleError(uri: vscode.Uri, e: Error & { code?: any }, doThrow: (boolean | ((error: any) => void)) = false): any {
if (e.code === 2 && shouldIgnoreNotFound(uri.path)) {
// Whenever a workspace opens, VSCode (and extensions) (indirectly) stat a bunch of files
// (.vscode/tasks.json etc, .git/, node_modules for NodeJS, pom.xml for Maven, ...)
this.logging.debug(`Ignored FileNotFound error for: ${uri}`, LOGGING_NO_STACKTRACE);
if (doThrow === true) throw e; else if (doThrow) return doThrow(e); else return;
}
Logging.error(`Error handling uri: ${uri}`, LOGGING_NO_STACKTRACE);
Logging.error(e, LOGGING_HANDLE_ERROR);
// Convert SSH2Stream error codes into VS Code errors

Loading…
Cancel
Save