diff --git a/extensions/typescript-language-features/package.json b/extensions/typescript-language-features/package.json index 9fef982d600..8eb4a71a13d 100644 --- a/extensions/typescript-language-features/package.json +++ b/extensions/typescript-language-features/package.json @@ -232,17 +232,6 @@ "description": "%typescript.tsserver.pluginPaths%", "scope": "machine" }, - "typescript.tsserver.trace": { - "type": "string", - "enum": [ - "off", - "messages", - "verbose" - ], - "default": "off", - "description": "%typescript.tsserver.trace%", - "scope": "window" - }, "javascript.suggest.completeFunctionCalls": { "type": "boolean", "default": false, diff --git a/extensions/typescript-language-features/src/logging/logger.ts b/extensions/typescript-language-features/src/logging/logger.ts index 96b7f95af14..33139b15537 100644 --- a/extensions/typescript-language-features/src/logging/logger.ts +++ b/extensions/typescript-language-features/src/logging/logger.ts @@ -6,28 +6,23 @@ import * as vscode from 'vscode'; import { memoize } from '../utils/memoize'; - -type LogLevel = 'Trace' | 'Info' | 'Error'; - export class Logger { @memoize - private get output(): vscode.OutputChannel { - return vscode.window.createOutputChannel('TypeScript'); + private get output(): vscode.LogOutputChannel { + return vscode.window.createOutputChannel('TypeScript', { log: true }); } - private data2String(data: any): string { - if (data instanceof Error) { - return data.stack || data.message; - } - if (data.success === false && data.message) { - return data.message; - } - return data.toString(); + public get logLevel(): vscode.LogLevel { + return this.output.logLevel; } - public info(message: string, data?: any): void { - this.logLevel('Info', message, data); + public info(message: string, ...args: any[]): void { + this.output.info(message, ...args); + } + + public trace(message: string, ...args: any[]): void { + this.output.trace(message, ...args); } public error(message: string, data?: any): void { @@ -35,24 +30,6 @@ export class Logger { if (data && data.message === 'No content available.') { return; } - this.logLevel('Error', message, data); - } - - public logLevel(level: LogLevel, message: string, data?: any): void { - this.output.appendLine(`[${level} - ${this.now()}] ${message}`); - if (data) { - this.output.appendLine(this.data2String(data)); - } - } - - private now(): string { - const now = new Date(); - return padLeft(now.getUTCHours() + '', 2, '0') - + ':' + padLeft(now.getMinutes() + '', 2, '0') - + ':' + padLeft(now.getUTCSeconds() + '', 2, '0') + '.' + now.getMilliseconds(); + this.output.error(message, ...(data ? [data] : [])); } } - -function padLeft(s: string, n: number, pad = ' ') { - return pad.repeat(Math.max(0, n - s.length)) + s; -} diff --git a/extensions/typescript-language-features/src/logging/tracer.ts b/extensions/typescript-language-features/src/logging/tracer.ts index bebd9fc54d4..e273181075d 100644 --- a/extensions/typescript-language-features/src/logging/tracer.ts +++ b/extensions/typescript-language-features/src/logging/tracer.ts @@ -5,98 +5,46 @@ import * as vscode from 'vscode'; import type * as Proto from '../tsServer/protocol/protocol'; +import { Disposable } from '../utils/dispose'; import { Logger } from './logger'; -enum Trace { - Off, - Messages, - Verbose, -} - -namespace Trace { - export function fromString(value: string): Trace { - value = value.toLowerCase(); - switch (value) { - case 'off': - return Trace.Off; - case 'messages': - return Trace.Messages; - case 'verbose': - return Trace.Verbose; - default: - return Trace.Off; - } - } -} - interface RequestExecutionMetadata { readonly queuingStartTime: number; } -export default class Tracer { - private trace?: Trace; +export default class Tracer extends Disposable { constructor( private readonly logger: Logger ) { - this.updateConfiguration(); - } - - public updateConfiguration() { - this.trace = Tracer.readTrace(); - } - - private static readTrace(): Trace { - let result: Trace = Trace.fromString(vscode.workspace.getConfiguration().get('typescript.tsserver.trace', 'off')); - if (result === Trace.Off && !!process.env.TSS_TRACE) { - result = Trace.Messages; - } - return result; + super(); } public traceRequest(serverId: string, request: Proto.Request, responseExpected: boolean, queueLength: number): void { - if (this.trace === Trace.Off) { - return; + if (this.logger.logLevel === vscode.LogLevel.Trace) { + this.trace(serverId, `Sending request: ${request.command} (${request.seq}). Response expected: ${responseExpected ? 'yes' : 'no'}. Current queue length: ${queueLength}`, request.arguments); } - let data: string | undefined = undefined; - if (this.trace === Trace.Verbose && request.arguments) { - data = `Arguments: ${JSON.stringify(request.arguments, null, 4)}`; - } - this.logTrace(serverId, `Sending request: ${request.command} (${request.seq}). Response expected: ${responseExpected ? 'yes' : 'no'}. Current queue length: ${queueLength}`, data); } public traceResponse(serverId: string, response: Proto.Response, meta: RequestExecutionMetadata): void { - if (this.trace === Trace.Off) { - return; + if (this.logger.logLevel === vscode.LogLevel.Trace) { + this.trace(serverId, `Response received: ${response.command} (${response.request_seq}). Request took ${Date.now() - meta.queuingStartTime} ms. Success: ${response.success} ${!response.success ? '. Message: ' + response.message : ''}`, response.body); } - let data: string | undefined = undefined; - if (this.trace === Trace.Verbose && response.body) { - data = `Result: ${JSON.stringify(response.body, null, 4)}`; - } - this.logTrace(serverId, `Response received: ${response.command} (${response.request_seq}). Request took ${Date.now() - meta.queuingStartTime} ms. Success: ${response.success} ${!response.success ? '. Message: ' + response.message : ''}`, data); } public traceRequestCompleted(serverId: string, command: string, request_seq: number, meta: RequestExecutionMetadata): any { - if (this.trace === Trace.Off) { - return; + if (this.logger.logLevel === vscode.LogLevel.Trace) { + this.trace(serverId, `Async response received: ${command} (${request_seq}). Request took ${Date.now() - meta.queuingStartTime} ms.`); } - this.logTrace(serverId, `Async response received: ${command} (${request_seq}). Request took ${Date.now() - meta.queuingStartTime} ms.`); } public traceEvent(serverId: string, event: Proto.Event): void { - if (this.trace === Trace.Off) { - return; + if (this.logger.logLevel === vscode.LogLevel.Trace) { + this.trace(serverId, `Event received: ${event.event} (${event.seq}).`, event.body); } - let data: string | undefined = undefined; - if (this.trace === Trace.Verbose && event.body) { - data = `Data: ${JSON.stringify(event.body, null, 4)}`; - } - this.logTrace(serverId, `Event received: ${event.event} (${event.seq}).`, data); } - public logTrace(serverId: string, message: string, data?: any): void { - if (this.trace !== Trace.Off) { - this.logger.logLevel('Trace', `<${serverId}> ${message}`, data); - } + public trace(serverId: string, message: string, data?: unknown): void { + this.logger.trace(`<${serverId}> ${message}`, ...(data ? [JSON.stringify(data, null, 4)] : [])); } } diff --git a/extensions/typescript-language-features/src/tsServer/cancellation.electron.ts b/extensions/typescript-language-features/src/tsServer/cancellation.electron.ts index 29ab6b2710c..3e1ad0a0c5c 100644 --- a/extensions/typescript-language-features/src/tsServer/cancellation.electron.ts +++ b/extensions/typescript-language-features/src/tsServer/cancellation.electron.ts @@ -22,7 +22,7 @@ export class NodeRequestCanceller implements OngoingRequestCanceller { if (!this.cancellationPipeName) { return false; } - this._tracer.logTrace(this._serverId, `TypeScript Server: trying to cancel ongoing request with sequence number ${seq}`); + this._tracer.trace(this._serverId, `TypeScript Server: trying to cancel ongoing request with sequence number ${seq}`); try { fs.writeFileSync(this.cancellationPipeName + seq, ''); } catch { diff --git a/extensions/typescript-language-features/src/tsServer/server.ts b/extensions/typescript-language-features/src/tsServer/server.ts index 7bdf6b83fe0..d1dc0233e96 100644 --- a/extensions/typescript-language-features/src/tsServer/server.ts +++ b/extensions/typescript-language-features/src/tsServer/server.ts @@ -299,7 +299,7 @@ export class SingleTsServer extends Disposable implements ITypeScriptServer { } private logTrace(message: string) { - this._tracer.logTrace(this._serverId, message); + this._tracer.trace(this._serverId, message); } private static readonly fenceCommands = new Set(['change', 'close', 'open', 'updateOpen']); diff --git a/extensions/typescript-language-features/src/typescriptServiceClient.ts b/extensions/typescript-language-features/src/typescriptServiceClient.ts index a3884bab936..a96a335af67 100644 --- a/extensions/typescript-language-features/src/typescriptServiceClient.ts +++ b/extensions/typescript-language-features/src/typescriptServiceClient.ts @@ -190,7 +190,6 @@ export default class TypeScriptServiceClient extends Disposable implements IType this.versionProvider.updateConfiguration(this._configuration); this._versionManager.updateConfiguration(this._configuration); this.pluginPathsProvider.updateConfiguration(this._configuration); - this.tracer.updateConfiguration(); if (this.serverState.type === ServerState.Type.Running) { if (!this._configuration.implicitProjectConfiguration.isEqualTo(oldConfiguration.implicitProjectConfiguration)) {