Skip to content

Commit 6afc083

Browse files
authored
Add Telemetry for VSC Notebooks (#12542)
* Added some missing telemetry for VS Code Notebooks * Track the type of notebook used in various operations (running cell, interrupting kernels, etc, determine whether user is performing such operations while in Native/Custom/Old editor) * Added a type for INobteookEditor (temporary, until VSC Notebook is stable) * Ensure users cannot opt into VSC Notebook Editor experiment when in VSC Stable.
1 parent d80bead commit 6afc083

17 files changed

Lines changed: 132 additions & 17 deletions

File tree

package.nls.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -536,5 +536,6 @@
536536
"DataScience.reloadCustomEditor": "Please reload VS Code to use the custom editor API",
537537
"DataScience.reloadVSCodeNotebookEditor": "Please reload VS Code to use the Notebook Editor",
538538
"DataScience.step": "Run next line (F10)",
539-
"DataScience.usingPreviewNotebookWithOtherNotebookWarning": "Using the Preview Notebook Editor along with the stable Notebook Editor is not recommended. Doing so could result in data loss or corruption of notebooks."
539+
"DataScience.usingPreviewNotebookWithOtherNotebookWarning": "Using the Preview Notebook Editor along with the stable Notebook Editor is not recommended. Doing so could result in data loss or corruption of notebooks.",
540+
"DataScience.previewNotebookOnlySupportedInVSCInsiders": "The Preview Notebook Editor is supported only in the Insiders version of Visual Studio Code."
540541
}

src/client/common/experiments/telemetry.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ import { sendTelemetryEvent, setSharedProperty } from '../../telemetry';
99
export class ExperimentationTelemetry implements IExperimentationTelemetry {
1010
public setSharedProperty(name: string, value: string): void {
1111
// Add the shared property to all telemetry being sent, not just events being sent by the experimentation package.
12-
setSharedProperty(name, value);
12+
// We are not in control of these props, just cast to `any`, i.e. we cannot strongly type these external props.
13+
// tslint:disable-next-line: no-any
14+
setSharedProperty(name as any, value as any);
1315
}
1416

1517
public postEvent(eventName: string, properties: Map<string, string>): void {

src/client/common/utils/localize.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -985,6 +985,10 @@ export namespace DataScience {
985985
'DataScience.usingPreviewNotebookWithOtherNotebookWarning',
986986
'Using the Preview Notebook Editor along with the stable Notebook Editor is not recommended. Doing so could result in data loss or corruption of notebooks.'
987987
);
988+
export const previewNotebookOnlySupportedInVSCInsiders = localize(
989+
'DataScience.previewNotebookOnlySupportedInVSCInsiders',
990+
'The Preview Notebook Editor is supported only in the Insiders version of Visual Studio Code.'
991+
);
988992
}
989993

990994
export namespace StartPage {

src/client/datascience/activation.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import '../common/extensions';
99
import { IPythonDaemonExecutionService, IPythonExecutionFactory } from '../common/process/types';
1010
import { IDisposableRegistry } from '../common/types';
1111
import { debounceAsync, swallowExceptions } from '../common/utils/decorators';
12-
import { sendTelemetryEvent } from '../telemetry';
12+
import { sendTelemetryEvent, setSharedProperty } from '../telemetry';
1313
import { JupyterDaemonModule, Telemetry } from './constants';
1414
import { ActiveEditorContextService } from './context/activeEditorContext';
1515
import { JupyterInterpreterService } from './jupyter/interpreter/jupyterInterpreterService';
@@ -37,9 +37,10 @@ export class Activation implements IExtensionSingleActivationService {
3737
this.tracker.startTracking();
3838
}
3939

40-
private onDidOpenNotebookEditor(_: INotebookEditor) {
40+
private onDidOpenNotebookEditor(e: INotebookEditor) {
4141
this.notebookOpened = true;
4242
this.PreWarmDaemonPool().ignoreErrors();
43+
setSharedProperty('ds_notebookeditor', e.type);
4344
sendTelemetryEvent(Telemetry.OpenNotebookAll);
4445
// Warm up our selected interpreter for the extension
4546
this.jupyterInterpreterService.setInitialInterpreter().ignoreErrors();

src/client/datascience/constants.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,21 @@ export enum NativeMouseCommandTelemetry {
395395
ToggleVariableExplorer = 'DATASCIENCE.NATIVE.MOUSE.TOGGLE_VARIABLE_EXPLORER'
396396
}
397397

398+
/**
399+
* Notebook editing in VS Code Notebooks is handled by VSC.
400+
* There's no way for us to know whether user added a cell using keyboard or not.
401+
* Similarly a cell could have been added as part of an undo operation.
402+
* All we know is previously user had n # of cells and now they have m # of cells.
403+
*/
404+
export enum VSCodeNativeTelemetry {
405+
AddCell = 'DATASCIENCE.VSCODE_NATIVE.INSERT_CELL',
406+
RunAllCells = 'DATASCIENCE.VSCODE_NATIVE.RUN_ALL',
407+
DeleteCell = 'DATASCIENCE.VSCODE_NATIVE.DELETE_CELL',
408+
MoveCell = 'DATASCIENCE.VSCODE_NATIVE.MOVE_CELL',
409+
ChangeToCode = 'DATASCIENCE.VSCODE_NATIVE.CHANGE_TO_CODE', // Not guaranteed to work see, https://github.com/microsoft/vscode/issues/100042
410+
ChangeToMarkdown = 'DATASCIENCE.VSCODE_NATIVE.CHANGE_TO_MARKDOWN' // Not guaranteed to work see, https://github.com/microsoft/vscode/issues/100042
411+
}
412+
398413
export namespace HelpLinks {
399414
export const PythonInteractiveHelpLink = 'https://aka.ms/pyaiinstall';
400415
export const JupyterDataRateHelpLink = 'https://aka.ms/AA5ggm0'; // This redirects here: https://jupyter-notebook.readthedocs.io/en/stable/config.html

src/client/datascience/context/activeEditorContext.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { PYTHON_LANGUAGE } from '../../common/constants';
1111
import { ContextKey } from '../../common/contextKey';
1212
import { NotebookEditorSupport } from '../../common/experiments/groups';
1313
import { IDisposable, IDisposableRegistry, IExperimentsManager } from '../../common/types';
14+
import { setSharedProperty } from '../../telemetry';
1415
import { EditorContexts } from '../constants';
1516
import { IInteractiveWindow, IInteractiveWindowProvider, INotebookEditor, INotebookEditorProvider } from '../types';
1617

@@ -86,6 +87,9 @@ export class ActiveEditorContextService implements IExtensionSingleActivationSer
8687
this.updateMergedContexts();
8788
}
8889
private onDidChangeActiveNotebookEditor(e?: INotebookEditor) {
90+
// This will ensure all subsequent telemetry will get the context of whether it is a custom/native/old notebook editor.
91+
// This is temporary, and once we ship native editor this needs to be removed.
92+
setSharedProperty('ds_notebookeditor', e?.type);
8993
this.nativeContext.set(!!e).ignoreErrors();
9094
this.updateMergedContexts();
9195
}

src/client/datascience/interactive-ipynb/nativeEditor.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ import { KernelSwitcher } from '../jupyter/kernels/kernelSwitcher';
9696
const nativeEditorDir = path.join(EXTENSION_ROOT_DIR, 'out', 'datascience-ui', 'notebook');
9797
@injectable()
9898
export class NativeEditor extends InteractiveBase implements INotebookEditor {
99+
public readonly type: 'old' | 'custom' = 'custom';
99100
public get onDidChangeViewState(): Event<void> {
100101
return this._onDidChangeViewState.event;
101102
}

src/client/datascience/interactive-ipynb/nativeEditorOldWebView.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ enum AskForSaveResult {
6262

6363
@injectable()
6464
export class NativeEditorOldWebView extends NativeEditor {
65+
public readonly type = 'old';
6566
public get visible(): boolean {
6667
return this.viewState.visible;
6768
}

src/client/datascience/notebook/contentProvider.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import type {
1616
import { ICommandManager } from '../../common/application/types';
1717
import { MARKDOWN_LANGUAGE } from '../../common/constants';
1818
import { DataScience } from '../../common/utils/localize';
19-
import { captureTelemetry } from '../../telemetry';
19+
import { captureTelemetry, sendTelemetryEvent, setSharedProperty } from '../../telemetry';
2020
import { Telemetry } from '../constants';
2121
import { INotebookStorageProvider } from '../interactive-ipynb/notebookStorageProvider';
2222
import { notebookModelToVSCNotebookData } from './helpers/helpers';
@@ -70,6 +70,9 @@ export class NotebookContentProvider implements INotebookContentProvider {
7070
const model = await (openContext.backupId
7171
? this.notebookStorage.load(uri, undefined, openContext.backupId)
7272
: this.notebookStorage.load(uri, undefined, true));
73+
74+
setSharedProperty('ds_notebookeditor', 'native');
75+
sendTelemetryEvent(Telemetry.CellCount, undefined, { count: model.cells.length });
7376
return notebookModelToVSCNotebookData(model);
7477
}
7578
@captureTelemetry(Telemetry.Save, undefined, true)

src/client/datascience/notebook/executionService.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { noop } from '../../common/utils/misc';
1717
import { StopWatch } from '../../common/utils/stopWatch';
1818
import { IServiceContainer } from '../../ioc/types';
1919
import { captureTelemetry, sendTelemetryEvent } from '../../telemetry';
20-
import { Commands, Telemetry } from '../constants';
20+
import { Commands, Telemetry, VSCodeNativeTelemetry } from '../constants';
2121
import { INotebookStorageProvider } from '../interactive-ipynb/notebookStorageProvider';
2222
import { IDataScienceErrorHandler, INotebook, INotebookModel, INotebookProvider } from '../types';
2323
import { findMappedNotebookCellModel } from './helpers/cellMappers';
@@ -81,6 +81,7 @@ export class NotebookExecutionService implements INotebookExecutionService {
8181
await this.executeIndividualCell(notebookAndModel, document, cell, token, stopWatch);
8282
}
8383
@captureTelemetry(Telemetry.ExecuteNativeCell, undefined, true)
84+
@captureTelemetry(VSCodeNativeTelemetry.RunAllCells, undefined, true)
8485
public async executeAllCells(document: NotebookDocument, token: CancellationToken): Promise<void> {
8586
const stopWatch = new StopWatch();
8687
const notebookAndModel = this.getNotebookAndModel(document);

0 commit comments

Comments
 (0)