This commit is contained in:
Phillip Tsui 2021-11-26 14:28:22 +00:00 committed by GitHub
commit 8fa99a64dc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 65 additions and 3 deletions

View file

@ -801,6 +801,9 @@ export class PersistentProtocol implements IMessagePassingProtocol {
private readonly _onSocketTimeout = new BufferedEmitter<void>();
readonly onSocketTimeout: Event<void> = this._onSocketTimeout.event;
private readonly _onTelemetryEvent = new BufferedEmitter<{ event: string, data: Object }>();
readonly onTelemetryEvent: Event<{ event: string, data: Object }> = this._onTelemetryEvent.event;
public get unacknowledgedCount(): number {
return this._outgoingMsgId - this._outgoingAckId;
}
@ -845,6 +848,10 @@ export class PersistentProtocol implements IMessagePassingProtocol {
this._socketDisposables = dispose(this._socketDisposables);
}
logTelemetry(event: string, data: Object): void {
this._onTelemetryEvent.fire({ event, data });
}
drain(): Promise<void> {
return this._socketWriter.drain();
}

View file

@ -545,6 +545,9 @@ export abstract class PersistentConnection extends Disposable {
private _isReconnecting: boolean;
private readonly _onTelemetryEvent = this._register(new Emitter<{ event: string, data: Object }>());
public readonly onTelemetryEvent = this._onTelemetryEvent.event;
constructor(private readonly _connectionType: ConnectionType, options: IConnectionOptions, reconnectionToken: string, protocol: PersistentProtocol) {
super();
this._options = options;
@ -577,6 +580,10 @@ export abstract class PersistentConnection extends Disposable {
this._beginReconnecting();
}));
this._register(protocol.onTelemetryEvent((e) => {
this._onTelemetryEvent.fire(e);
}));
PersistentConnection._instances.push(this);
if (PersistentConnection._permanentFailure) {
@ -584,6 +591,10 @@ export abstract class PersistentConnection extends Disposable {
}
}
public logTelemetryEvent(event: string, data: Object): void {
this._onTelemetryEvent.fire({ event, data });
}
private async _beginReconnecting(): Promise<void> {
// Only have one reconnection loop active at a time.
if (this._isReconnecting) {

View file

@ -73,7 +73,18 @@ const args = minimist(process.argv.slice(2), {
})();
// custom process.exit logic...
const nativeExit: IExitFn = process.exit.bind(process);
const nodeExit: IExitFn = process.exit.bind(process);
const nativeExit: IExitFn = async () => {
// Try to get a call stack so we can see what code path decided to exit.
const err = new Error();
await sendTelemetry('ext.host.about-to-native-exit', { stack: err.stack });
nodeExit();
// Should be unreachable...
await sendTelemetry('ext.host.about-to-native-exit-FAILED', { stack: err.stack });
process.abort();
};
function patchProcess(allowExit: boolean) {
process.exit = function (code?: number) {
if (allowExit) {
@ -96,6 +107,34 @@ interface IRendererConnection {
initData: IInitData;
}
export interface IExtHostTelemetryMessage {
type: 'ext-host-telemetry',
event: string,
data: unknown,
}
async function sendTelemetry(event: string, data?: any): Promise<void> {
if (process.send) {
const message: IExtHostTelemetryMessage = {
type: 'ext-host-telemetry',
event,
data: {
...data
},
};
await new Promise<void>((resolve, reject) => {
process.send!(message, (err: Error | null) => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
}
// This calls exit directly in case the initialization is not finished and we need to exit
// Otherwise, if initialization completed we go to extensionHostMain.terminate()
let onTerminate = function (reason: string) {
@ -115,8 +154,13 @@ function _createExtHostProtocol(): Promise<PersistentProtocol> {
const reconnectionGraceTime = ProtocolConstants.ReconnectionGraceTime;
const reconnectionShortGraceTime = ProtocolConstants.ReconnectionShortGraceTime;
const disconnectRunner1 = new ProcessTimeRunOnceScheduler(() => onTerminate('renderer disconnected for too long (1)'), reconnectionGraceTime);
const disconnectRunner2 = new ProcessTimeRunOnceScheduler(() => onTerminate('renderer disconnected for too long (2)'), reconnectionShortGraceTime);
const disconnectRunnerExit = (message: string) => {
sendTelemetry('ext.host.exit.disconnect-runner');
onTerminate(message);
};
const disconnectRunner1 = new ProcessTimeRunOnceScheduler(() => disconnectRunnerExit('renderer disconnected for too long (1)'), reconnectionGraceTime);
const disconnectRunner2 = new ProcessTimeRunOnceScheduler(() => disconnectRunnerExit('renderer disconnected for too long (2)'), reconnectionShortGraceTime);
process.on('message', (msg: IExtHostSocketMessage | IExtHostReduceGraceTimeMessage, handle: net.Socket) => {
if (msg && msg.type === 'VSCODE_EXTHOST_IPC_SOCKET') {