mirror of
https://github.com/coder/code-server.git
synced 2026-06-21 01:17:10 +02:00
chore(vscode): update to 1.54.2
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
120
lib/vscode/src/vs/platform/log/node/spdlogLog.ts
Normal file
120
lib/vscode/src/vs/platform/log/node/spdlogLog.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user