chore(vscode): update to 1.54.2

This commit is contained in:
Joe Previte
2021-03-11 10:27:10 -07:00
1459 changed files with 53404 additions and 51004 deletions

View File

@@ -3,25 +3,35 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ILogService, DEFAULT_LOG_LEVEL, LogLevel, LogServiceAdapter } from 'vs/platform/log/common/log';
import { DEFAULT_LOG_LEVEL, LogLevel, AdapterLogger, ILogger } from 'vs/platform/log/common/log';
interface IAutomatedWindow {
codeAutomationLog(type: string, args: any[]): void;
}
function logLevelToString(level: LogLevel): string {
switch (level) {
case LogLevel.Trace: return 'trace';
case LogLevel.Debug: return 'debug';
case LogLevel.Info: return 'info';
case LogLevel.Warning: return 'warn';
case LogLevel.Error: return 'error';
case LogLevel.Critical: return 'critical';
}
return 'info';
}
/**
* A logger that is used when VSCode is running in the web with
* an automation such as playwright. We expect a global codeAutomationLog
* to be defined that we can use to log to.
*/
export class ConsoleLogInAutomationService extends LogServiceAdapter implements ILogService {
export class ConsoleLogInAutomationLogger extends AdapterLogger implements ILogger {
declare codeAutomationLog: any;
declare readonly _serviceBrand: undefined;
constructor(logLevel: LogLevel = DEFAULT_LOG_LEVEL) {
super({ consoleLog: (type, args) => this.consoleLog(type, args) }, logLevel);
super({ log: (level, args) => this.consoleLog(logLevelToString(level), args) }, logLevel);
}
private consoleLog(type: string, args: any[]): void {

View File

@@ -3,14 +3,14 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ILogService, LogLevel, AbstractLogService, DEFAULT_LOG_LEVEL } from 'vs/platform/log/common/log';
import { ILogService, LogLevel, AbstractLogger, DEFAULT_LOG_LEVEL, ILogger } from 'vs/platform/log/common/log';
interface ILog {
level: LogLevel;
args: any[];
}
function getLogFunction(logger: ILogService, level: LogLevel): Function {
function getLogFunction(logger: ILogger, level: LogLevel): Function {
switch (level) {
case LogLevel.Trace: return logger.trace;
case LogLevel.Debug: return logger.debug;
@@ -22,11 +22,11 @@ function getLogFunction(logger: ILogService, level: LogLevel): Function {
}
}
export class BufferLogService extends AbstractLogService implements ILogService {
export class BufferLogService extends AbstractLogger implements ILogService {
declare readonly _serviceBrand: undefined;
private buffer: ILog[] = [];
private _logger: ILogService | undefined = undefined;
private _logger: ILogger | undefined = undefined;
constructor(logLevel: LogLevel = DEFAULT_LOG_LEVEL) {
super();
@@ -38,7 +38,7 @@ export class BufferLogService extends AbstractLogService implements ILogService
}));
}
set logger(logger: ILogService) {
set logger(logger: ILogger) {
this._logger = logger;
for (const { level, args } of this.buffer) {

View File

@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ILogService, LogLevel, AbstractLogService, ILoggerService, ILogger } from 'vs/platform/log/common/log';
import { ILogService, LogLevel, AbstractLogger, ILoggerService, ILogger } from 'vs/platform/log/common/log';
import { URI } from 'vs/base/common/uri';
import { ByteSize, FileOperationError, FileOperationResult, IFileService, whenProviderRegistered } from 'vs/platform/files/common/files';
import { Queue } from 'vs/base/common/async';
@@ -15,9 +15,7 @@ import { BufferLogService } from 'vs/platform/log/common/bufferLog';
const MAX_FILE_SIZE = 5 * ByteSize.MB;
export class FileLogService extends AbstractLogService implements ILogService {
declare readonly _serviceBrand: undefined;
export class FileLogger extends AbstractLogger implements ILogger {
private readonly initializePromise: Promise<void>;
private readonly queue: Queue<void>;
@@ -176,12 +174,12 @@ export class FileLoggerService extends Disposable implements ILoggerService {
this._register(logService.onDidChangeLogLevel(level => this.loggers.forEach(logger => logger.setLevel(level))));
}
getLogger(resource: URI): ILogger {
createLogger(resource: URI): ILogger {
let logger = this.loggers.get(resource.toString());
if (!logger) {
logger = new BufferLogService(this.logService.getLevel());
this.loggers.set(resource.toString(), logger);
whenProviderRegistered(resource, this.fileService).then(() => (<BufferLogService>logger).logger = this.instantiationService.createInstance(FileLogService, basename(resource), resource, this.logService.getLevel()));
whenProviderRegistered(resource, this.fileService).then(() => (<BufferLogService>logger).logger = this.instantiationService.createInstance(FileLogger, basename(resource), resource, this.logService.getLevel()));
}
return logger;
}

View File

@@ -8,7 +8,6 @@ import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
import { isWindows } from 'vs/base/common/platform';
import { Event, Emitter } from 'vs/base/common/event';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { LoggerChannelClient } from 'vs/platform/log/common/logIpc';
import { URI } from 'vs/base/common/uri';
import { toErrorMessage } from 'vs/base/common/errorMessage';
@@ -53,13 +52,39 @@ export interface ILogService extends ILogger {
readonly _serviceBrand: undefined;
}
export interface ILoggerOptions {
/**
* Name of the logger.
*/
name?: string;
/**
* Do not create rotating files if max size exceeds.
*/
donotRotate?: boolean;
/**
* Do not use formatters.
*/
donotUseFormatters?: boolean;
/**
* If set, logger logs the message always.
*/
always?: boolean;
}
export interface ILoggerService {
readonly _serviceBrand: undefined;
getLogger(file: URI): ILogger;
/**
* Creates a logger
*/
createLogger(file: URI, options?: ILoggerOptions): ILogger;
}
export abstract class AbstractLogService extends Disposable {
export abstract class AbstractLogger extends Disposable {
private level: LogLevel = DEFAULT_LOG_LEVEL;
private readonly _onDidChangeLogLevel: Emitter<LogLevel> = this._register(new Emitter<LogLevel>());
@@ -78,9 +103,85 @@ export abstract class AbstractLogService extends Disposable {
}
export class ConsoleLogMainService extends AbstractLogService implements ILogService {
export abstract class AbstractMessageLogger extends AbstractLogger implements ILogger {
protected abstract log(level: LogLevel, message: string): void;
constructor(private readonly logAlways?: boolean) {
super();
}
private checkLogLevel(level: LogLevel): boolean {
return this.logAlways || this.getLevel() <= level;
}
trace(message: string, ...args: any[]): void {
if (this.checkLogLevel(LogLevel.Trace)) {
this.log(LogLevel.Trace, this.format([message, ...args]));
}
}
debug(message: string, ...args: any[]): void {
if (this.checkLogLevel(LogLevel.Debug)) {
this.log(LogLevel.Debug, this.format([message, ...args]));
}
}
info(message: string, ...args: any[]): void {
if (this.checkLogLevel(LogLevel.Info)) {
this.log(LogLevel.Info, this.format([message, ...args]));
}
}
warn(message: string, ...args: any[]): void {
if (this.checkLogLevel(LogLevel.Warning)) {
this.log(LogLevel.Warning, this.format([message, ...args]));
}
}
error(message: string | Error, ...args: any[]): void {
if (this.checkLogLevel(LogLevel.Error)) {
if (message instanceof Error) {
const array = Array.prototype.slice.call(arguments) as any[];
array[0] = message.stack;
this.log(LogLevel.Error, this.format(array));
} else {
this.log(LogLevel.Error, this.format([message, ...args]));
}
}
}
critical(message: string | Error, ...args: any[]): void {
if (this.checkLogLevel(LogLevel.Critical)) {
this.log(LogLevel.Critical, this.format([message, ...args]));
}
}
flush(): void { }
private format(args: any): string {
let result = '';
for (let i = 0; i < args.length; i++) {
let a = args[i];
if (typeof a === 'object') {
try {
a = JSON.stringify(a);
} catch (e) { }
}
result += (i > 0 ? ' ' : '') + a;
}
return result;
}
}
export class ConsoleMainLogger extends AbstractLogger implements ILogger {
declare readonly _serviceBrand: undefined;
private useColors: boolean;
constructor(logLevel: LogLevel = DEFAULT_LOG_LEVEL) {
@@ -159,9 +260,7 @@ export class ConsoleLogMainService extends AbstractLogService implements ILogSer
}
export class ConsoleLogService extends AbstractLogService implements ILogService {
declare readonly _serviceBrand: undefined;
export class ConsoleLogger extends AbstractLogger implements ILogger {
constructor(logLevel: LogLevel = DEFAULT_LOG_LEVEL) {
super();
@@ -213,48 +312,46 @@ export class ConsoleLogService extends AbstractLogService implements ILogService
}
}
export class LogServiceAdapter extends AbstractLogService implements ILogService {
export class AdapterLogger extends AbstractLogger implements ILogger {
declare readonly _serviceBrand: undefined;
constructor(private readonly adapter: { consoleLog: (type: string, args: any[]) => void }, logLevel: LogLevel = DEFAULT_LOG_LEVEL) {
constructor(private readonly adapter: { log: (logLevel: LogLevel, args: any[]) => void }, logLevel: LogLevel = DEFAULT_LOG_LEVEL) {
super();
this.setLevel(logLevel);
}
trace(message: string, ...args: any[]): void {
if (this.getLevel() <= LogLevel.Trace) {
this.adapter.consoleLog('trace', [this.extractMessage(message), ...args]);
this.adapter.log(LogLevel.Trace, [this.extractMessage(message), ...args]);
}
}
debug(message: string, ...args: any[]): void {
if (this.getLevel() <= LogLevel.Debug) {
this.adapter.consoleLog('debug', [this.extractMessage(message), ...args]);
this.adapter.log(LogLevel.Debug, [this.extractMessage(message), ...args]);
}
}
info(message: string, ...args: any[]): void {
if (this.getLevel() <= LogLevel.Info) {
this.adapter.consoleLog('info', [this.extractMessage(message), ...args]);
this.adapter.log(LogLevel.Info, [this.extractMessage(message), ...args]);
}
}
warn(message: string | Error, ...args: any[]): void {
if (this.getLevel() <= LogLevel.Warning) {
this.adapter.consoleLog('warn', [this.extractMessage(message), ...args]);
this.adapter.log(LogLevel.Warning, [this.extractMessage(message), ...args]);
}
}
error(message: string | Error, ...args: any[]): void {
if (this.getLevel() <= LogLevel.Error) {
this.adapter.consoleLog('error', [this.extractMessage(message), ...args]);
this.adapter.log(LogLevel.Error, [this.extractMessage(message), ...args]);
}
}
critical(message: string | Error, ...args: any[]): void {
if (this.getLevel() <= LogLevel.Critical) {
this.adapter.consoleLog('critical', [this.extractMessage(message), ...args]);
this.adapter.log(LogLevel.Critical, [this.extractMessage(message), ...args]);
}
}
@@ -275,19 +372,10 @@ export class LogServiceAdapter extends AbstractLogService implements ILogService
}
}
export class ConsoleLogInMainService extends LogServiceAdapter implements ILogService {
export class MultiplexLogService extends AbstractLogger implements ILogService {
declare readonly _serviceBrand: undefined;
constructor(client: LoggerChannelClient, logLevel: LogLevel = DEFAULT_LOG_LEVEL) {
super({ consoleLog: (type, args) => client.consoleLog(type, args) }, logLevel);
}
}
export class MultiplexLogService extends AbstractLogService implements ILogService {
declare readonly _serviceBrand: undefined;
constructor(private readonly logServices: ReadonlyArray<ILogService>) {
constructor(private readonly logServices: ReadonlyArray<ILogger>) {
super();
if (logServices.length) {
this.setLevel(logServices[0].getLevel());
@@ -350,52 +438,52 @@ export class MultiplexLogService extends AbstractLogService implements ILogServi
}
}
export class DelegatedLogService extends Disposable implements ILogService {
export class LogService extends Disposable implements ILogService {
declare readonly _serviceBrand: undefined;
constructor(private logService: ILogService) {
constructor(private logger: ILogger) {
super();
this._register(logService);
this._register(logger);
}
get onDidChangeLogLevel(): Event<LogLevel> {
return this.logService.onDidChangeLogLevel;
return this.logger.onDidChangeLogLevel;
}
setLevel(level: LogLevel): void {
this.logService.setLevel(level);
this.logger.setLevel(level);
}
getLevel(): LogLevel {
return this.logService.getLevel();
return this.logger.getLevel();
}
trace(message: string, ...args: any[]): void {
this.logService.trace(message, ...args);
this.logger.trace(message, ...args);
}
debug(message: string, ...args: any[]): void {
this.logService.debug(message, ...args);
this.logger.debug(message, ...args);
}
info(message: string, ...args: any[]): void {
this.logService.info(message, ...args);
this.logger.info(message, ...args);
}
warn(message: string, ...args: any[]): void {
this.logService.warn(message, ...args);
this.logger.warn(message, ...args);
}
error(message: string | Error, ...args: any[]): void {
this.logService.error(message, ...args);
this.logger.error(message, ...args);
}
critical(message: string | Error, ...args: any[]): void {
this.logService.critical(message, ...args);
this.logger.critical(message, ...args);
}
flush(): void {
this.logService.flush();
this.logger.flush();
}
}

View File

@@ -4,10 +4,11 @@
*--------------------------------------------------------------------------------------------*/
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc';
import { LogLevel, ILogService, DelegatedLogService } from 'vs/platform/log/common/log';
import { LogLevel, ILogService, LogService, ILoggerService, ILogger, AbstractMessageLogger, ILoggerOptions, AdapterLogger } from 'vs/platform/log/common/log';
import { Event } from 'vs/base/common/event';
import { URI } from 'vs/base/common/uri';
export class LoggerChannel implements IServerChannel {
export class LogLevelChannel implements IServerChannel {
onDidChangeLogLevel: Event<LogLevel>;
@@ -23,35 +24,17 @@ export class LoggerChannel implements IServerChannel {
throw new Error(`Event not found: ${event}`);
}
call(_: unknown, command: string, arg?: any): Promise<any> {
async call(_: unknown, command: string, arg?: any): Promise<any> {
switch (command) {
case 'setLevel': this.service.setLevel(arg); return Promise.resolve();
case 'consoleLog': this.consoleLog(arg[0], arg[1]); return Promise.resolve();
case 'setLevel': return this.service.setLevel(arg);
}
throw new Error(`Call not found: ${command}`);
}
private consoleLog(severity: string, args: string[]): void {
let consoleFn = console.log;
switch (severity) {
case 'error':
consoleFn = console.error;
break;
case 'warn':
consoleFn = console.warn;
break;
case 'info':
consoleFn = console.info;
break;
}
consoleFn.call(console, ...args);
}
}
export class LoggerChannelClient {
export class LogLevelChannelClient {
constructor(private channel: IChannel) { }
@@ -60,22 +43,131 @@ export class LoggerChannelClient {
}
setLevel(level: LogLevel): void {
LoggerChannelClient.setLevel(this.channel, level);
LogLevelChannelClient.setLevel(this.channel, level);
}
public static setLevel(channel: IChannel, level: LogLevel): Promise<void> {
return channel.call('setLevel', level);
}
consoleLog(severity: string, args: string[]): void {
this.channel.call('consoleLog', [severity, args]);
}
export class LoggerChannel implements IServerChannel {
private readonly loggers = new Map<string, ILogger>();
constructor(private readonly loggerService: ILoggerService) { }
listen(_: unknown, event: string): Event<any> {
throw new Error(`Event not found: ${event}`);
}
async call(_: unknown, command: string, arg?: any): Promise<any> {
switch (command) {
case 'createLogger': this.createLogger(URI.revive(arg[0]), arg[1]); return;
case 'log': return this.log(URI.revive(arg[0]), arg[1]);
case 'consoleLog': return this.consoleLog(arg[0], arg[1]);
}
throw new Error(`Call not found: ${command}`);
}
private createLogger(file: URI, options: ILoggerOptions): void {
this.loggers.set(file.toString(), this.loggerService.createLogger(file, options));
}
private consoleLog(level: LogLevel, args: any[]): void {
let consoleFn = console.log;
switch (level) {
case LogLevel.Error:
consoleFn = console.error;
break;
case LogLevel.Warning:
consoleFn = console.warn;
break;
case LogLevel.Info:
consoleFn = console.info;
break;
}
consoleFn.call(console, ...args);
}
private log(file: URI, messages: [LogLevel, string][]): void {
const logger = this.loggers.get(file.toString());
if (!logger) {
throw new Error('Create the logger before logging');
}
for (const [level, message] of messages) {
switch (level) {
case LogLevel.Trace: logger.trace(message); break;
case LogLevel.Debug: logger.debug(message); break;
case LogLevel.Info: logger.info(message); break;
case LogLevel.Warning: logger.warn(message); break;
case LogLevel.Error: logger.error(message); break;
case LogLevel.Critical: logger.critical(message); break;
default: throw new Error('Invalid log level');
}
}
}
}
export class FollowerLogService extends DelegatedLogService implements ILogService {
export class LoggerChannelClient implements ILoggerService {
declare readonly _serviceBrand: undefined;
constructor(private parent: LoggerChannelClient, logService: ILogService) {
constructor(private readonly channel: IChannel) { }
createConsoleMainLogger(): ILogger {
return new AdapterLogger({
log: (level: LogLevel, args: any[]) => {
this.channel.call('consoleLog', [level, args]);
}
});
}
createLogger(file: URI, options?: ILoggerOptions): ILogger {
return new Logger(this.channel, file, options);
}
}
class Logger extends AbstractMessageLogger {
private isLoggerCreated: boolean = false;
private buffer: [LogLevel, string][] = [];
constructor(
private readonly channel: IChannel,
private readonly file: URI,
loggerOptions?: ILoggerOptions,
) {
super(loggerOptions?.always);
this.channel.call('createLogger', [file, loggerOptions])
.then(() => {
this._log(this.buffer);
this.isLoggerCreated = true;
});
}
protected log(level: LogLevel, message: string) {
this._log([[level, message]]);
}
private _log(messages: [LogLevel, string][]) {
if (this.isLoggerCreated) {
this.channel.call('log', [this.file, messages]);
} else {
this.buffer.push(...messages);
}
}
}
export class FollowerLogService extends LogService implements ILogService {
declare readonly _serviceBrand: undefined;
constructor(private parent: LogLevelChannelClient, logService: ILogService) {
super(logService);
this._register(parent.onDidChangeLogLevel(level => logService.setLevel(level)));
}

View File

@@ -3,45 +3,54 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ILogService, ILoggerService, ILogger } from 'vs/platform/log/common/log';
import { ILogService, ILoggerService, ILogger, ILoggerOptions, LogLevel } from 'vs/platform/log/common/log';
import { Disposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { basename, extname, dirname } from 'vs/base/common/resources';
import { basename } from 'vs/base/common/resources';
import { Schemas } from 'vs/base/common/network';
import { FileLogService } from 'vs/platform/log/common/fileLogService';
import { SpdLogService } from 'vs/platform/log/node/spdlogService';
import { FileLogger } from 'vs/platform/log/common/fileLog';
import { SpdLogLogger } from 'vs/platform/log/node/spdlogLog';
import { IFileService } from 'vs/platform/files/common/files';
import { generateUuid } from 'vs/base/common/uuid';
export class LoggerService extends Disposable implements ILoggerService {
declare readonly _serviceBrand: undefined;
private readonly loggers = new Map<string, ILogger>();
private readonly logLevelChangeableLoggers: ILogger[] = [];
constructor(
@ILogService private logService: ILogService,
@IFileService private fileService: IFileService
) {
super();
this._register(logService.onDidChangeLogLevel(level => this.loggers.forEach(logger => logger.setLevel(level))));
this._register(logService.onDidChangeLogLevel(level => this.logLevelChangeableLoggers.forEach(logger => logger.setLevel(level))));
}
getLogger(resource: URI): ILogger {
createLogger(resource: URI, options?: ILoggerOptions): ILogger {
let logger = this.loggers.get(resource.toString());
if (!logger) {
if (resource.scheme === Schemas.file) {
const baseName = basename(resource);
const ext = extname(resource);
logger = new SpdLogService(baseName.substring(0, baseName.length - ext.length), dirname(resource).fsPath, this.logService.getLevel());
logger = new SpdLogLogger(options?.name || generateUuid(), resource.fsPath, !options?.donotRotate, this.logService.getLevel());
if (options?.donotUseFormatters) {
(<SpdLogLogger>logger).clearFormatters();
}
} else {
logger = new FileLogService(basename(resource), resource, this.logService.getLevel(), this.fileService);
logger = new FileLogger(options?.name ?? basename(resource), resource, this.logService.getLevel(), this.fileService);
}
this.loggers.set(resource.toString(), logger);
if (options?.always) {
logger.setLevel(LogLevel.Trace);
} else {
this.logLevelChangeableLoggers.push(logger);
}
}
return logger;
}
dispose(): void {
this.logLevelChangeableLoggers.splice(0, this.logLevelChangeableLoggers.length);
this.loggers.forEach(logger => logger.dispose());
this.loggers.clear();
super.dispose();

View File

@@ -0,0 +1,120 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { LogLevel, ILogger, AbstractMessageLogger } from 'vs/platform/log/common/log';
import * as spdlog from 'spdlog';
import { ByteSize } from 'vs/platform/files/common/files';
async function createSpdLogLogger(name: string, logfilePath: string, filesize: number, filecount: number): Promise<spdlog.RotatingLogger | null> {
// Do not crash if spdlog cannot be loaded
try {
const _spdlog = await import('spdlog');
_spdlog.setAsyncMode(8192, 500);
return _spdlog.createRotatingLoggerAsync(name, logfilePath, filesize, filecount);
} catch (e) {
console.error(e);
}
return null;
}
export function createRotatingLogger(name: string, filename: string, filesize: number, filecount: number): spdlog.RotatingLogger {
const _spdlog: typeof spdlog = require.__$__nodeRequire('spdlog');
return _spdlog.createRotatingLogger(name, filename, filesize, filecount);
}
interface ILog {
level: LogLevel;
message: string;
}
function log(logger: spdlog.RotatingLogger, level: LogLevel, message: string): void {
switch (level) {
case LogLevel.Trace: logger.trace(message); break;
case LogLevel.Debug: logger.debug(message); break;
case LogLevel.Info: logger.info(message); break;
case LogLevel.Warning: logger.warn(message); break;
case LogLevel.Error: logger.error(message); break;
case LogLevel.Critical: logger.critical(message); break;
default: throw new Error('Invalid log level');
}
}
export class SpdLogLogger extends AbstractMessageLogger implements ILogger {
private buffer: ILog[] = [];
private readonly _loggerCreationPromise: Promise<void>;
private _logger: spdlog.RotatingLogger | undefined;
constructor(
private readonly name: string,
private readonly filepath: string,
private readonly rotating: boolean,
level: LogLevel
) {
super();
this.setLevel(level);
this._loggerCreationPromise = this._createSpdLogLogger();
this._register(this.onDidChangeLogLevel(level => {
if (this._logger) {
this._logger.setLevel(level);
}
}));
}
private _createSpdLogLogger(): Promise<void> {
const filecount = this.rotating ? 6 : 1;
const filesize = (30 / filecount) * ByteSize.MB;
return createSpdLogLogger(this.name, this.filepath, filesize, filecount)
.then(logger => {
if (logger) {
this._logger = logger;
this._logger.setLevel(this.getLevel());
for (const { level, message } of this.buffer) {
log(this._logger, level, message);
}
this.buffer = [];
}
});
}
protected log(level: LogLevel, message: string): void {
if (this._logger) {
log(this._logger, level, message);
} else if (this.getLevel() <= level) {
this.buffer.push({ level, message });
}
}
clearFormatters(): void {
if (this._logger) {
this._logger.clearFormatters();
} else {
this._loggerCreationPromise.then(() => this.clearFormatters());
}
}
flush(): void {
if (this._logger) {
this._logger.flush();
} else {
this._loggerCreationPromise.then(() => this.flush());
}
}
dispose(): void {
if (this._logger) {
this.disposeLogger();
} else {
this._loggerCreationPromise.then(() => this.disposeLogger());
}
}
private disposeLogger(): void {
if (this._logger) {
this._logger.drop();
this._logger = undefined;
}
}
}

View File

@@ -1,174 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as path from 'vs/base/common/path';
import { ILogService, LogLevel, AbstractLogService } from 'vs/platform/log/common/log';
import * as spdlog from 'spdlog';
import { ByteSize } from 'vs/platform/files/common/files';
async function createSpdLogLogger(processName: string, logsFolder: string): Promise<spdlog.RotatingLogger | null> {
// Do not crash if spdlog cannot be loaded
try {
const _spdlog = await import('spdlog');
_spdlog.setAsyncMode(8192, 500);
const logfilePath = path.join(logsFolder, `${processName}.log`);
return _spdlog.createRotatingLoggerAsync(processName, logfilePath, 5 * ByteSize.MB, 6);
} catch (e) {
console.error(e);
}
return null;
}
export function createRotatingLogger(name: string, filename: string, filesize: number, filecount: number): spdlog.RotatingLogger {
const _spdlog: typeof spdlog = require.__$__nodeRequire('spdlog');
return _spdlog.createRotatingLogger(name, filename, filesize, filecount);
}
interface ILog {
level: LogLevel;
message: string;
}
function log(logger: spdlog.RotatingLogger, level: LogLevel, message: string): void {
switch (level) {
case LogLevel.Trace: logger.trace(message); break;
case LogLevel.Debug: logger.debug(message); break;
case LogLevel.Info: logger.info(message); break;
case LogLevel.Warning: logger.warn(message); break;
case LogLevel.Error: logger.error(message); break;
case LogLevel.Critical: logger.critical(message); break;
default: throw new Error('Invalid log level');
}
}
export class SpdLogService extends AbstractLogService implements ILogService {
declare readonly _serviceBrand: undefined;
private buffer: ILog[] = [];
private _loggerCreationPromise: Promise<void> | undefined = undefined;
private _logger: spdlog.RotatingLogger | undefined;
constructor(private readonly name: string, private readonly logsFolder: string, level: LogLevel) {
super();
this.setLevel(level);
this._createSpdLogLogger();
this._register(this.onDidChangeLogLevel(level => {
if (this._logger) {
this._logger.setLevel(level);
}
}));
}
private _createSpdLogLogger(): Promise<void> {
if (!this._loggerCreationPromise) {
this._loggerCreationPromise = createSpdLogLogger(this.name, this.logsFolder)
.then(logger => {
if (logger) {
this._logger = logger;
this._logger.setLevel(this.getLevel());
for (const { level, message } of this.buffer) {
log(this._logger, level, message);
}
this.buffer = [];
}
});
}
return this._loggerCreationPromise;
}
private _log(level: LogLevel, message: string): void {
if (this._logger) {
log(this._logger, level, message);
} else if (this.getLevel() <= level) {
this.buffer.push({ level, message });
}
}
trace(message: string, ...args: any[]): void {
if (this.getLevel() <= LogLevel.Trace) {
this._log(LogLevel.Trace, this.format([message, ...args]));
}
}
debug(message: string, ...args: any[]): void {
if (this.getLevel() <= LogLevel.Debug) {
this._log(LogLevel.Debug, this.format([message, ...args]));
}
}
info(message: string, ...args: any[]): void {
if (this.getLevel() <= LogLevel.Info) {
this._log(LogLevel.Info, this.format([message, ...args]));
}
}
warn(message: string, ...args: any[]): void {
if (this.getLevel() <= LogLevel.Warning) {
this._log(LogLevel.Warning, this.format([message, ...args]));
}
}
error(message: string | Error, ...args: any[]): void {
if (this.getLevel() <= LogLevel.Error) {
if (message instanceof Error) {
const array = Array.prototype.slice.call(arguments) as any[];
array[0] = message.stack;
this._log(LogLevel.Error, this.format(array));
} else {
this._log(LogLevel.Error, this.format([message, ...args]));
}
}
}
critical(message: string | Error, ...args: any[]): void {
if (this.getLevel() <= LogLevel.Critical) {
this._log(LogLevel.Critical, this.format([message, ...args]));
}
}
flush(): void {
if (this._logger) {
this._logger.flush();
} else if (this._loggerCreationPromise) {
this._loggerCreationPromise.then(() => this.flush());
}
}
dispose(): void {
if (this._logger) {
this.disposeLogger();
} else if (this._loggerCreationPromise) {
this._loggerCreationPromise.then(() => this.disposeLogger());
}
this._loggerCreationPromise = undefined;
}
private disposeLogger(): void {
if (this._logger) {
this._logger.drop();
this._logger = undefined;
}
}
private format(args: any): string {
let result = '';
for (let i = 0; i < args.length; i++) {
let a = args[i];
if (typeof a === 'object') {
try {
a = JSON.stringify(a);
} catch (e) { }
}
result += (i > 0 ? ' ' : '') + a;
}
return result;
}
}