Switch TS ext to use LogOutputChannel (#179205)

Fixes #176479
This commit is contained in:
Matt Bierner
2023-04-05 10:44:21 -07:00
committed by GitHub
parent 5da5017a2c
commit cc69fb1aad
6 changed files with 26 additions and 113 deletions

View File

@@ -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,

View File

@@ -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;
}

View File

@@ -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<string>('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)] : []));
}
}

View File

@@ -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 {

View File

@@ -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']);

View File

@@ -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)) {