Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle nb file open failure/halt properly. #176920

Merged
merged 1 commit into from Mar 13, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
132 changes: 81 additions & 51 deletions src/vs/workbench/contrib/notebook/browser/notebookEditor.ts
Expand Up @@ -6,6 +6,7 @@
import * as DOM from 'vs/base/browser/dom';
import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { IAction, toAction } from 'vs/base/common/actions';
import { timeout } from 'vs/base/common/async';
import { CancellationToken } from 'vs/base/common/cancellation';
import { Emitter, Event } from 'vs/base/common/event';
import { DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle';
Expand Down Expand Up @@ -168,6 +169,13 @@ export class NotebookEditor extends EditorPane implements INotebookEditorPane {

override async setInput(input: NotebookEditorInput, options: INotebookEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken, noRetry?: boolean): Promise<void> {
try {
let perfMarksCaptured = false;
const fileOpenMonitor = timeout(10000);
fileOpenMonitor.then(() => {
perfMarksCaptured = true;
this._handlePerfMark(perf, input);
});

const perf = new NotebookPerfMarks();
perf.mark('startTime');
const group = this.group!;
Expand Down Expand Up @@ -236,58 +244,12 @@ export class NotebookEditor extends EditorPane implements INotebookEditorPane {

perf.mark('editorLoaded');

type WorkbenchNotebookOpenClassification = {
owner: 'rebornix';
comment: 'The notebook file open metrics. Used to get a better understanding of the performance of notebook file opening';
scheme: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'File system provider scheme for the notebook resource' };
ext: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'File extension for the notebook resource' };
viewType: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The view type of the notebook editor' };
extensionActivated: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Extension activation time for the resource opening' };
inputLoaded: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Editor Input loading time for the resource opening' };
webviewCommLoaded: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Webview initialization time for the resource opening' };
customMarkdownLoaded: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Custom markdown loading time for the resource opening' };
editorLoaded: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Overall editor loading time for the resource opening' };
};

type WorkbenchNotebookOpenEvent = {
scheme: string;
ext: string;
viewType: string;
extensionActivated: number;
inputLoaded: number;
webviewCommLoaded: number;
customMarkdownLoaded: number | undefined;
editorLoaded: number;
};

const perfMarks = perf.value;
if (perfMarks) {
const startTime = perfMarks['startTime'];
const extensionActivated = perfMarks['extensionActivated'];
const inputLoaded = perfMarks['inputLoaded'];
const customMarkdownLoaded = perfMarks['customMarkdownLoaded'];
const editorLoaded = perfMarks['editorLoaded'];

if (
startTime !== undefined
&& extensionActivated !== undefined
&& inputLoaded !== undefined
&& editorLoaded !== undefined
) {
this.telemetryService.publicLog2<WorkbenchNotebookOpenEvent, WorkbenchNotebookOpenClassification>('notebook/editorOpenPerf', {
scheme: model.notebook.uri.scheme,
ext: extname(model.notebook.uri),
viewType: model.notebook.viewType,
extensionActivated: extensionActivated - startTime,
inputLoaded: inputLoaded - startTime,
webviewCommLoaded: inputLoaded - startTime,
customMarkdownLoaded: typeof customMarkdownLoaded === 'number' ? customMarkdownLoaded - startTime : undefined,
editorLoaded: editorLoaded - startTime
});
} else {
console.warn(`notebook file open perf marks are broken: startTime ${startTime}, extensionActivated ${extensionActivated}, inputLoaded ${inputLoaded}, customMarkdownLoaded ${customMarkdownLoaded}, editorLoaded ${editorLoaded}`);
}
fileOpenMonitor.cancel();
if (perfMarksCaptured) {
return;
}

this._handlePerfMark(perf, input);
} catch (e) {
console.warn(e);
const error = createEditorOpenError(e instanceof Error ? e : new Error((e ? e.message : '')), [
Expand Down Expand Up @@ -323,6 +285,74 @@ export class NotebookEditor extends EditorPane implements INotebookEditorPane {
}
}

private _handlePerfMark(perf: NotebookPerfMarks, input: NotebookEditorInput) {
const perfMarks = perf.value;

type WorkbenchNotebookOpenClassification = {
owner: 'rebornix';
comment: 'The notebook file open metrics. Used to get a better understanding of the performance of notebook file opening';
scheme: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'File system provider scheme for the notebook resource' };
ext: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'File extension for the notebook resource' };
viewType: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The view type of the notebook editor' };
extensionActivated: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Extension activation time for the resource opening' };
inputLoaded: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Editor Input loading time for the resource opening' };
webviewCommLoaded: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Webview initialization time for the resource opening' };
customMarkdownLoaded: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Custom markdown loading time for the resource opening' };
editorLoaded: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Overall editor loading time for the resource opening' };
};

type WorkbenchNotebookOpenEvent = {
scheme: string;
ext: string;
viewType: string;
extensionActivated: number;
inputLoaded: number;
webviewCommLoaded: number;
customMarkdownLoaded: number | undefined;
editorLoaded: number;
};

const startTime = perfMarks['startTime'];
const extensionActivated = perfMarks['extensionActivated'];
const inputLoaded = perfMarks['inputLoaded'];
const customMarkdownLoaded = perfMarks['customMarkdownLoaded'];
const editorLoaded = perfMarks['editorLoaded'];

let extensionActivationTimespan = -1;
let inputLoadingTimespan = -1;
let webviewCommLoadingTimespan = -1;
let customMarkdownLoadingTimespan = -1;
let editorLoadingTimespan = -1;

if (startTime !== undefined && extensionActivated !== undefined) {
extensionActivationTimespan = extensionActivated - startTime;

if (inputLoaded !== undefined) {
inputLoadingTimespan = inputLoaded - extensionActivated;
webviewCommLoadingTimespan = inputLoaded - extensionActivated; // TODO@rebornix, we don't track webview comm anymore
}

if (customMarkdownLoaded !== undefined) {
customMarkdownLoadingTimespan = customMarkdownLoaded - startTime;
}

if (editorLoaded !== undefined) {
editorLoadingTimespan = editorLoaded - startTime;
}
}

this.telemetryService.publicLog2<WorkbenchNotebookOpenEvent, WorkbenchNotebookOpenClassification>('notebook/editorOpenPerf', {
scheme: input.resource.scheme,
ext: extname(input.resource),
viewType: input.viewType,
extensionActivated: extensionActivationTimespan,
inputLoaded: inputLoadingTimespan,
webviewCommLoaded: webviewCommLoadingTimespan,
customMarkdownLoaded: customMarkdownLoadingTimespan,
editorLoaded: editorLoadingTimespan
});
}

override clearInput(): void {
this._inputListener.clear();

Expand Down