Add trace log level, traceCall decorator and use in webgl

- New 'trace' log level in the API, you should expect very spammy logs when
  trace is on and filter them down. As opposed to 'debug' which should be more
  readable.
- traceCall decorator logs the args and return value of the decorated method.
  Wecan use this on key functions in various parts of the code to assist
  debugging issues that are hard to reproduce such as #4665.
- Decorated a few webgl render methods for #4665.
- There's an early exit in traceCall when not on the trace log level so the
  runtime impact when not in trace is negligable.

Part of #4665
This commit is contained in:
Daniel Imms
2023-08-18 11:04:23 -07:00
parent 3b3b23a2fd
commit 0b54c9a5d6
11 changed files with 91 additions and 25 deletions
+1
View File
@@ -104,6 +104,7 @@ export class MockCoreService implements ICoreService {
export class MockLogService implements ILogService {
public serviceBrand: any;
public logLevel = LogLevelEnum.DEBUG;
public trace(message: any, ...optionalParams: any[]): void { }
public debug(message: any, ...optionalParams: any[]): void { }
public info(message: any, ...optionalParams: any[]): void { }
public warn(message: any, ...optionalParams: any[]): void { }
+37
View File
@@ -21,6 +21,7 @@ interface IConsole {
declare const console: IConsole;
const optionsKeyToLogLevel: { [key: string]: LogLevelEnum } = {
trace: LogLevelEnum.TRACE,
debug: LogLevelEnum.DEBUG,
info: LogLevelEnum.INFO,
warn: LogLevelEnum.WARN,
@@ -42,6 +43,9 @@ export class LogService extends Disposable implements ILogService {
super();
this._updateLogLevel();
this.register(this._optionsService.onSpecificOptionChange('logLevel', () => this._updateLogLevel()));
// For trace logging, assume the latest created log service is valid
traceLogger = this;
}
private _updateLogLevel(): void {
@@ -61,6 +65,12 @@ export class LogService extends Disposable implements ILogService {
type.call(console, (this._optionsService.options.logger ? '' : LOG_PREFIX) + message, ...optionalParams);
}
public trace(message: string, ...optionalParams: any[]): void {
if (this._logLevel <= LogLevelEnum.TRACE) {
this._log(this._optionsService.options.logger?.trace.bind(this._optionsService.options.logger) ?? console.log, message, optionalParams);
}
}
public debug(message: string, ...optionalParams: any[]): void {
if (this._logLevel <= LogLevelEnum.DEBUG) {
this._log(this._optionsService.options.logger?.debug.bind(this._optionsService.options.logger) ?? console.log, message, optionalParams);
@@ -85,3 +95,30 @@ export class LogService extends Disposable implements ILogService {
}
}
}
let traceLogger: ILogService;
export function setTraceLogger(logger: ILogService): void {
traceLogger = logger;
}
/**
* A decorator that can be used to automatically log trace calls to the decorated function.
*/
export function traceCall(_target: any, key: string, descriptor: any): any {
if (typeof descriptor.value !== 'function') {
throw new Error('not supported');
}
const fnKey = 'value';
const fn = descriptor.value;
descriptor[fnKey] = function (...args: any[]) {
// Early exit
if (traceLogger.logLevel !== LogLevelEnum.TRACE) {
return fn.apply(this, args);
}
traceLogger.trace(`GlyphRenderer#${fn.name}(${args.map(e => JSON.stringify(e)).join(', ')})`);
const result = fn.apply(this, args);
traceLogger.trace(`GlyphRenderer#${fn.name} return`, result);
return result;
};
}
+8 -6
View File
@@ -142,11 +142,12 @@ export interface IInstantiationService {
}
export enum LogLevelEnum {
DEBUG = 0,
INFO = 1,
WARN = 2,
ERROR = 3,
OFF = 4
TRACE = 0,
DEBUG = 1,
INFO = 2,
WARN = 3,
ERROR = 4,
OFF = 5
}
export const ILogService = createDecorator<ILogService>('LogService');
@@ -155,6 +156,7 @@ export interface ILogService {
readonly logLevel: LogLevelEnum;
trace(message: any, ...optionalParams: any[]): void;
debug(message: any, ...optionalParams: any[]): void;
info(message: any, ...optionalParams: any[]): void;
warn(message: any, ...optionalParams: any[]): void;
@@ -201,7 +203,7 @@ export interface IOptionsService {
}
export type FontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900' | number;
export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'off';
export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'off';
export interface ITerminalOptions {
allowProposedApi?: boolean;