debug: use native logging in extension host

https://github.com/microsoft/vscode/issues/104686
This commit is contained in:
Connor Peet 2020-11-23 11:19:31 -08:00
parent 2a1c8bbaf2
commit 206fbe0bb3
No known key found for this signature in database
GPG key ID: CF8FD2EA0DBC61BD
6 changed files with 34 additions and 58 deletions

35
src/bootstrap-fork.js vendored
View file

@ -135,18 +135,43 @@ function pipeLoggingToParent() {
&& !(obj instanceof Date);
}
/**
*
* @param {'log' | 'warn' | 'error'} severity
* @param {string} args
*/
function safeSendConsoleMessage(severity, args) {
safeSend({ type: '__$console', severity, arguments: args });
}
/**
* @param {'log' | 'info' | 'warn' | 'error'} method
* @param {'log' | 'warn' | 'error'} severity
*/
function wrapConsoleMethod(method, severity) {
if (process.env.VSCODE_LOG_NATIVE === 'true') {
const original = console[method];
console[method] = function () {
safeSendConsoleMessage(severity, safeToArray(arguments));
original.apply(console, arguments);
};
} else {
console[method] = function () { safeSendConsoleMessage(severity, safeToArray(arguments)); };
}
}
// Pass console logging to the outside so that we have it in the main side if told so
if (process.env.VERBOSE_LOGGING === 'true') {
console.log = function () { safeSend({ type: '__$console', severity: 'log', arguments: safeToArray(arguments) }); };
console.info = function () { safeSend({ type: '__$console', severity: 'log', arguments: safeToArray(arguments) }); };
console.warn = function () { safeSend({ type: '__$console', severity: 'warn', arguments: safeToArray(arguments) }); };
} else {
wrapConsoleMethod('log', 'log');
wrapConsoleMethod('warn', 'log');
wrapConsoleMethod('error', 'warn');
} else if (process.env.VSCODE_LOG_NATIVE !== 'true') {
console.log = function () { /* ignore */ };
console.warn = function () { /* ignore */ };
console.info = function () { /* ignore */ };
}
console.error = function () { safeSend({ type: '__$console', severity: 'error', arguments: safeToArray(arguments) }); };
wrapConsoleMethod('error', 'error');
}
function handleExceptions() {

View file

@ -5,7 +5,6 @@
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { Event } from 'vs/base/common/event';
import { IRemoteConsoleLog } from 'vs/base/common/console';
import { IProcessEnvironment } from 'vs/base/common/platform';
export const IExtensionHostDebugService = createDecorator<IExtensionHostDebugService>('extensionHostDebugService');
@ -16,11 +15,6 @@ export interface IAttachSessionEvent {
port: number;
}
export interface ILogToSessionEvent {
sessionId: string;
log: IRemoteConsoleLog;
}
export interface ITerminateSessionEvent {
sessionId: string;
subId?: string;
@ -50,9 +44,6 @@ export interface IExtensionHostDebugService {
attachSession(sessionId: string, port: number, subId?: string): void;
readonly onAttachSession: Event<IAttachSessionEvent>;
logToSession(sessionId: string, log: IRemoteConsoleLog): void;
readonly onLogToSession: Event<ILogToSessionEvent>;
terminateSession(sessionId: string, subId?: string): void;
readonly onTerminateSession: Event<ITerminateSessionEvent>;

View file

@ -4,9 +4,8 @@
*--------------------------------------------------------------------------------------------*/
import { IServerChannel, IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IReloadSessionEvent, ICloseSessionEvent, IAttachSessionEvent, ILogToSessionEvent, ITerminateSessionEvent, IExtensionHostDebugService, IOpenExtensionWindowResult } from 'vs/platform/debug/common/extensionHostDebug';
import { IReloadSessionEvent, ICloseSessionEvent, IAttachSessionEvent, ITerminateSessionEvent, IExtensionHostDebugService, IOpenExtensionWindowResult } from 'vs/platform/debug/common/extensionHostDebug';
import { Event, Emitter } from 'vs/base/common/event';
import { IRemoteConsoleLog } from 'vs/base/common/console';
import { Disposable } from 'vs/base/common/lifecycle';
import { IProcessEnvironment } from 'vs/base/common/platform';
@ -17,7 +16,6 @@ export class ExtensionHostDebugBroadcastChannel<TContext> implements IServerChan
private readonly _onCloseEmitter = new Emitter<ICloseSessionEvent>();
private readonly _onReloadEmitter = new Emitter<IReloadSessionEvent>();
private readonly _onTerminateEmitter = new Emitter<ITerminateSessionEvent>();
private readonly _onLogToEmitter = new Emitter<ILogToSessionEvent>();
private readonly _onAttachEmitter = new Emitter<IAttachSessionEvent>();
call(ctx: TContext, command: string, arg?: any): Promise<any> {
@ -28,8 +26,6 @@ export class ExtensionHostDebugBroadcastChannel<TContext> implements IServerChan
return Promise.resolve(this._onReloadEmitter.fire({ sessionId: arg[0] }));
case 'terminate':
return Promise.resolve(this._onTerminateEmitter.fire({ sessionId: arg[0] }));
case 'log':
return Promise.resolve(this._onLogToEmitter.fire({ sessionId: arg[0], log: arg[1] }));
case 'attach':
return Promise.resolve(this._onAttachEmitter.fire({ sessionId: arg[0], port: arg[1], subId: arg[2] }));
}
@ -44,8 +40,6 @@ export class ExtensionHostDebugBroadcastChannel<TContext> implements IServerChan
return this._onReloadEmitter.event;
case 'terminate':
return this._onTerminateEmitter.event;
case 'log':
return this._onLogToEmitter.event;
case 'attach':
return this._onAttachEmitter.event;
}
@ -85,14 +79,6 @@ export class ExtensionHostDebugChannelClient extends Disposable implements IExte
return this.channel.listen('attach');
}
logToSession(sessionId: string, log: IRemoteConsoleLog): void {
this.channel.call('log', [sessionId, log]);
}
get onLogToSession(): Event<ILogToSessionEvent> {
return this.channel.listen('log');
}
terminateSession(sessionId: string, subId?: string): void {
this.channel.call('terminate', [sessionId, subId]);
}

View file

@ -10,22 +10,18 @@ import { IRemoteConsoleLog, log } from 'vs/base/common/console';
import { logRemoteEntry } from 'vs/workbench/services/extensions/common/remoteConsoleUtil';
import { parseExtensionDevOptions } from 'vs/workbench/services/extensions/common/extensionDevOptions';
import { ILogService } from 'vs/platform/log/common/log';
import { IExtensionHostDebugService } from 'vs/platform/debug/common/extensionHostDebug';
@extHostNamedCustomer(MainContext.MainThreadConsole)
export class MainThreadConsole implements MainThreadConsoleShape {
private readonly _isExtensionDevHost: boolean;
private readonly _isExtensionDevTestFromCli: boolean;
constructor(
extHostContext: IExtHostContext,
_extHostContext: IExtHostContext,
@IEnvironmentService private readonly _environmentService: IEnvironmentService,
@ILogService private readonly _logService: ILogService,
@IExtensionHostDebugService private readonly _extensionHostDebugService: IExtensionHostDebugService,
) {
const devOpts = parseExtensionDevOptions(this._environmentService);
this._isExtensionDevHost = devOpts.isExtensionDevHost;
this._isExtensionDevTestFromCli = devOpts.isExtensionDevTestFromCli;
}
@ -43,10 +39,5 @@ export class MainThreadConsole implements MainThreadConsoleShape {
if (this._isExtensionDevTestFromCli) {
logRemoteEntry(this._logService, entry);
}
// Broadcast to other windows if we are in development mode
else if (this._environmentService.debugExtensionHost.debugId && (!this._environmentService.isBuilt || this._isExtensionDevHost)) {
this._extensionHostDebugService.logToSession(this._environmentService.debugExtensionHost.debugId, entry);
}
}
}

View file

@ -25,7 +25,6 @@ import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/bro
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IWorkspaceContextService, WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { parse, getFirstFrame } from 'vs/base/common/console';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IAction, Action } from 'vs/base/common/actions';
@ -149,16 +148,6 @@ export class DebugService implements IDebugService {
session.disconnect();
}
}));
this.toDispose.push(this.extensionHostDebugService.onLogToSession(event => {
const session = this.model.getSession(event.sessionId, true);
if (session) {
// extension logged output -> show it in REPL
const sev = event.log.severity === 'warn' ? severity.Warning : event.log.severity === 'error' ? severity.Error : severity.Info;
const { args, stack } = parse(event.log);
const frame = !!stack ? getFirstFrame(stack) : undefined;
session.logToRepl(sev, args, frame);
}
}));
this.toDispose.push(this.viewModel.onDidFocusStackFrame(() => {
this.onStateChange();

View file

@ -151,13 +151,12 @@ export class LocalProcessExtensionHost implements IExtensionHost {
this._messageProtocol = Promise.all([
this._tryListenOnPipe(),
this._tryFindDebugPort()
]).then(data => {
const pipeName = data[0];
const portNumber = data[1];
]).then(([pipeName, portNumber]) => {
const env = objects.mixin(objects.deepClone(process.env), {
AMD_ENTRYPOINT: 'vs/workbench/services/extensions/node/extensionHostProcess',
PIPE_LOGGING: 'true',
VERBOSE_LOGGING: true,
VSCODE_LOG_NATIVE: this._isExtensionDevHost,
VSCODE_IPC_HOOK_EXTHOST: pipeName,
VSCODE_HANDLES_UNCAUGHT_ERRORS: true,
VSCODE_LOG_STACK: !this._isExtensionDevTestFromCli && (this._isExtensionDevHost || !this._environmentService.isBuilt || this._productService.quality !== 'stable' || this._environmentService.verbose),
@ -497,11 +496,6 @@ export class LocalProcessExtensionHost implements IExtensionHost {
// Send to local console
log(entry, 'Extension Host');
// Broadcast to other windows if we are in development mode
if (this._environmentService.debugExtensionHost.debugId && (!this._environmentService.isBuilt || this._isExtensionDevHost)) {
this._extensionHostDebugService.logToSession(this._environmentService.debugExtensionHost.debugId, entry);
}
}
}