Skip to content

Commit 57ea0b6

Browse files
committed
Add telemetry to capture perceived time taken to start jupyter and run cell (#10217)
* Add telemetry * Only for nb For #10098 For #10212
1 parent 7a01a9a commit 57ea0b6

File tree

6 files changed

+36
-2
lines changed

6 files changed

+36
-2
lines changed

news/3 Code Health/10098.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Telemetry to capture connections to `localhost` using the connect to remote Jupyter server feature.

news/3 Code Health/10212.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Telemetry to capture perceived startup times of Jupyter and time to execute a cell.

src/client/datascience/constants.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ export enum Telemetry {
160160
SubmitCellThroughInput = 'DATASCIENCE.SUBMITCELLFROMREPL',
161161
ConnectLocalJupyter = 'DS_INTERNAL.CONNECTLOCALJUPYTER',
162162
ConnectRemoteJupyter = 'DS_INTERNAL.CONNECTREMOTEJUPYTER',
163+
ConnectRemoteJupyterViaLocalHost = 'DS_INTERNAL.CONNECTREMOTEJUPYTER_VIA_LOCALHOST',
163164
ConnectFailedJupyter = 'DS_INTERNAL.CONNECTFAILEDJUPYTER',
164165
ConnectRemoteFailedJupyter = 'DS_INTERNAL.CONNECTREMOTEFAILEDJUPYTER',
165166
StartSessionFailedJupyter = 'DS_INTERNAL.START_SESSION_FAILED_JUPYTER',
@@ -209,6 +210,8 @@ export enum Telemetry {
209210
ExecuteCell = 'DATASCIENCE.EXECUTE_CELL_TIME',
210211
ExecuteCellPerceivedCold = 'DS_INTERNAL.EXECUTE_CELL_PERCEIVED_COLD',
211212
ExecuteCellPerceivedWarm = 'DS_INTERNAL.EXECUTE_CELL_PERCEIVED_WARM',
213+
PerceivedJupyterStartupNotebook = 'DS_INTERNAL.PERCEIVED_JUPYTER_STARTUP_NOTEBOOK',
214+
StartExecuteNotebookCellPerceivedCold = 'DS_INTERNAL.START_EXECUTE_NOTEBOOK_CELL_PERCEIVED_COLD',
212215
WebviewStartup = 'DS_INTERNAL.WEBVIEW_STARTUP',
213216
VariableExplorerFetchTime = 'DS_INTERNAL.VARIABLE_EXPLORER_FETCH_TIME',
214217
WebviewStyleUpdate = 'DS_INTERNAL.WEBVIEW_STYLE_UPDATE',

src/client/datascience/interactive-common/interactiveBase.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { IFileSystem } from '../../common/platform/types';
2020
import { IConfigurationService, IDisposableRegistry, IExperimentsManager } from '../../common/types';
2121
import { createDeferred, Deferred } from '../../common/utils/async';
2222
import * as localize from '../../common/utils/localize';
23+
import { StopWatch } from '../../common/utils/stopWatch';
2324
import { IInterpreterService, PythonInterpreter } from '../../interpreter/contracts';
2425
import { captureTelemetry, sendTelemetryEvent } from '../../telemetry';
2526
import { generateCellRangesFromDocument } from '../cellFactory';
@@ -78,6 +79,7 @@ import { InteractiveWindowMessageListener } from './interactiveWindowMessageList
7879
export abstract class InteractiveBase extends WebViewHost<IInteractiveWindowMapping> implements IInteractiveBase {
7980
private unfinishedCells: ICell[] = [];
8081
private restartingKernel: boolean = false;
82+
private perceivedJupyterStartupTelemetryCaptured: boolean = false;
8183
private potentiallyUnfinishedStatus: Disposable[] = [];
8284
private addSysInfoPromise: Deferred<boolean> | undefined;
8385
private _notebook: INotebook | undefined;
@@ -457,8 +459,9 @@ export abstract class InteractiveBase extends WebViewHost<IInteractiveWindowMapp
457459
// tslint:disable-next-line: max-func-body-length
458460
protected async submitCode(code: string, file: string, line: number, id?: string, _editor?: TextEditor, debug?: boolean): Promise<boolean> {
459461
traceInfo(`Submitting code for ${this.id}`);
462+
const stopWatch =
463+
this._notebook && !this.perceivedJupyterStartupTelemetryCaptured ? new StopWatch() : undefined;
460464
let result = true;
461-
462465
// Do not execute or render empty code cells
463466
const cellMatcher = new CellMatcher(this.configService.getSettings().datascience);
464467
if (cellMatcher.stripFirstMarker(code).length === 0) {
@@ -511,7 +514,16 @@ export abstract class InteractiveBase extends WebViewHost<IInteractiveWindowMapp
511514
if (file !== Identifiers.EmptyFileName) {
512515
await this._notebook.execute(`__file__ = '${file.replace(/\\/g, '\\\\')}'`, file, line, uuid(), undefined, true);
513516
}
514-
517+
if (stopWatch && !this.perceivedJupyterStartupTelemetryCaptured) {
518+
this.perceivedJupyterStartupTelemetryCaptured = true;
519+
sendTelemetryEvent(Telemetry.PerceivedJupyterStartupNotebook, stopWatch?.elapsedTime);
520+
const disposable = this._notebook.onSessionStatusChanged(e => {
521+
if (e === ServerStatus.Busy) {
522+
sendTelemetryEvent(Telemetry.StartExecuteNotebookCellPerceivedCold, stopWatch?.elapsedTime);
523+
disposable.dispose();
524+
}
525+
});
526+
}
515527
const observable = this._notebook.executeObservable(code, file, line, id, false);
516528

517529
// Indicate we executed some code

src/client/datascience/jupyter/jupyterExecution.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ import { JupyterWaitForIdleError } from './jupyterWaitForIdleError';
3131
import { KernelSelector, KernelSpecInterpreter } from './kernels/kernelSelector';
3232
import { NotebookStarter } from './notebookStarter';
3333

34+
const LocalHosts = ['localhost', '127.0.0.1', '::1'];
35+
3436
export class JupyterExecutionBase implements IJupyterExecution {
3537
private usablePythonInterpreter: PythonInterpreter | undefined;
3638
private eventEmitter: EventEmitter<void> = new EventEmitter<void>();
@@ -143,6 +145,9 @@ export class JupyterExecutionBase implements IJupyterExecution {
143145
try {
144146
// Start or connect to the process
145147
[connection, kernelSpecInterpreter] = await Promise.all([this.startOrConnect(options, cancelToken), kernelSpecInterpreterPromise]);
148+
if (!connection.localLaunch && LocalHosts.includes(connection.hostName.toLowerCase())) {
149+
sendTelemetryEvent(Telemetry.ConnectRemoteJupyterViaLocalHost);
150+
}
146151
// Create a server tha t we will then attempt to connect to.
147152
result = this.serviceContainer.get<INotebookServer>(INotebookServer);
148153

src/client/telemetry/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1436,6 +1436,10 @@ export interface IEventNamePropertyMapping {
14361436
[Telemetry.ConnectFailedJupyter]: never | undefined;
14371437
[Telemetry.ConnectLocalJupyter]: never | undefined;
14381438
[Telemetry.ConnectRemoteJupyter]: never | undefined;
1439+
/**
1440+
* Connecting to an existing Jupyter server, but connecting to localhost.
1441+
*/
1442+
[Telemetry.ConnectRemoteJupyterViaLocalHost]: never | undefined;
14391443
[Telemetry.ConnectRemoteFailedJupyter]: never | undefined;
14401444
[Telemetry.ConnectRemoteSelfCertFailedJupyter]: never | undefined;
14411445
[Telemetry.RegisterAndUseInterpreterAsKernel]: never | undefined;
@@ -1469,6 +1473,14 @@ export interface IEventNamePropertyMapping {
14691473
* If `notebook = true`, this its telemetry for native editor/notebooks.
14701474
*/
14711475
[Telemetry.ExecuteCellPerceivedWarm]: undefined | { notebook: boolean };
1476+
/**
1477+
* Time take for jupyter server to start and be ready to run first user cell.
1478+
*/
1479+
[Telemetry.PerceivedJupyterStartupNotebook]: never | undefined;
1480+
/**
1481+
* Time take for jupyter server to be busy from the time user first hit `run` cell until jupyter reports it is busy running a cell.
1482+
*/
1483+
[Telemetry.StartExecuteNotebookCellPerceivedCold]: never | undefined;
14721484
[Telemetry.ExecuteNativeCell]: never | undefined;
14731485
[Telemetry.ExpandAll]: never | undefined;
14741486
[Telemetry.ExportNotebook]: never | undefined;

0 commit comments

Comments
 (0)