Skip to content

Commit ea0fb54

Browse files
authored
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 f1a8f63 commit ea0fb54

File tree

6 files changed

+37
-2
lines changed

6 files changed

+37
-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
@@ -178,6 +178,7 @@ export enum Telemetry {
178178
SubmitCellThroughInput = 'DATASCIENCE.SUBMITCELLFROMREPL',
179179
ConnectLocalJupyter = 'DS_INTERNAL.CONNECTLOCALJUPYTER',
180180
ConnectRemoteJupyter = 'DS_INTERNAL.CONNECTREMOTEJUPYTER',
181+
ConnectRemoteJupyterViaLocalHost = 'DS_INTERNAL.CONNECTREMOTEJUPYTER_VIA_LOCALHOST',
181182
ConnectFailedJupyter = 'DS_INTERNAL.CONNECTFAILEDJUPYTER',
182183
ConnectRemoteFailedJupyter = 'DS_INTERNAL.CONNECTREMOTEFAILEDJUPYTER',
183184
StartSessionFailedJupyter = 'DS_INTERNAL.START_SESSION_FAILED_JUPYTER',
@@ -227,6 +228,8 @@ export enum Telemetry {
227228
ExecuteCell = 'DATASCIENCE.EXECUTE_CELL_TIME',
228229
ExecuteCellPerceivedCold = 'DS_INTERNAL.EXECUTE_CELL_PERCEIVED_COLD',
229230
ExecuteCellPerceivedWarm = 'DS_INTERNAL.EXECUTE_CELL_PERCEIVED_WARM',
231+
PerceivedJupyterStartupNotebook = 'DS_INTERNAL.PERCEIVED_JUPYTER_STARTUP_NOTEBOOK',
232+
StartExecuteNotebookCellPerceivedCold = 'DS_INTERNAL.START_EXECUTE_NOTEBOOK_CELL_PERCEIVED_COLD',
230233
WebviewStartup = 'DS_INTERNAL.WEBVIEW_STARTUP',
231234
VariableExplorerFetchTime = 'DS_INTERNAL.VARIABLE_EXPLORER_FETCH_TIME',
232235
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
@@ -41,6 +41,7 @@ import { IFileSystem } from '../../common/platform/types';
4141
import { IConfigurationService, IDisposableRegistry, IExperimentsManager } from '../../common/types';
4242
import { createDeferred, Deferred } from '../../common/utils/async';
4343
import * as localize from '../../common/utils/localize';
44+
import { StopWatch } from '../../common/utils/stopWatch';
4445
import { IInterpreterService, PythonInterpreter } from '../../interpreter/contracts';
4546
import { captureTelemetry, sendTelemetryEvent } from '../../telemetry';
4647
import { generateCellRangesFromDocument } from '../cellFactory';
@@ -101,6 +102,7 @@ import { InteractiveWindowMessageListener } from './interactiveWindowMessageList
101102
export abstract class InteractiveBase extends WebViewHost<IInteractiveWindowMapping> implements IInteractiveBase {
102103
private unfinishedCells: ICell[] = [];
103104
private restartingKernel: boolean = false;
105+
private perceivedJupyterStartupTelemetryCaptured: boolean = false;
104106
private potentiallyUnfinishedStatus: Disposable[] = [];
105107
private addSysInfoPromise: Deferred<boolean> | undefined;
106108
private _notebook: INotebook | undefined;
@@ -500,8 +502,9 @@ export abstract class InteractiveBase extends WebViewHost<IInteractiveWindowMapp
500502
debug?: boolean
501503
): Promise<boolean> {
502504
traceInfo(`Submitting code for ${this.id}`);
505+
const stopWatch =
506+
this._notebook && !this.perceivedJupyterStartupTelemetryCaptured ? new StopWatch() : undefined;
503507
let result = true;
504-
505508
// Do not execute or render empty code cells
506509
const cellMatcher = new CellMatcher(this.configService.getSettings().datascience);
507510
if (cellMatcher.stripFirstMarker(code).length === 0) {
@@ -568,7 +571,16 @@ export abstract class InteractiveBase extends WebViewHost<IInteractiveWindowMapp
568571
true
569572
);
570573
}
571-
574+
if (stopWatch && !this.perceivedJupyterStartupTelemetryCaptured) {
575+
this.perceivedJupyterStartupTelemetryCaptured = true;
576+
sendTelemetryEvent(Telemetry.PerceivedJupyterStartupNotebook, stopWatch?.elapsedTime);
577+
const disposable = this._notebook.onSessionStatusChanged(e => {
578+
if (e === ServerStatus.Busy) {
579+
sendTelemetryEvent(Telemetry.StartExecuteNotebookCellPerceivedCold, stopWatch?.elapsedTime);
580+
disposable.dispose();
581+
}
582+
});
583+
}
572584
const observable = this._notebook.executeObservable(code, file, line, id, false);
573585

574586
// Indicate we executed some code

src/client/datascience/jupyter/jupyterExecution.ts

Lines changed: 6 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>();
@@ -159,6 +161,10 @@ export class JupyterExecutionBase implements IJupyterExecution {
159161
this.startOrConnect(options, cancelToken),
160162
kernelSpecInterpreterPromise
161163
]);
164+
165+
if (!connection.localLaunch && LocalHosts.includes(connection.hostName.toLowerCase())) {
166+
sendTelemetryEvent(Telemetry.ConnectRemoteJupyterViaLocalHost);
167+
}
162168
// Create a server tha t we will then attempt to connect to.
163169
result = this.serviceContainer.get<INotebookServer>(INotebookServer);
164170

src/client/telemetry/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1460,6 +1460,10 @@ export interface IEventNamePropertyMapping {
14601460
[Telemetry.ConnectFailedJupyter]: never | undefined;
14611461
[Telemetry.ConnectLocalJupyter]: never | undefined;
14621462
[Telemetry.ConnectRemoteJupyter]: never | undefined;
1463+
/**
1464+
* Connecting to an existing Jupyter server, but connecting to localhost.
1465+
*/
1466+
[Telemetry.ConnectRemoteJupyterViaLocalHost]: never | undefined;
14631467
[Telemetry.ConnectRemoteFailedJupyter]: never | undefined;
14641468
[Telemetry.ConnectRemoteSelfCertFailedJupyter]: never | undefined;
14651469
[Telemetry.RegisterAndUseInterpreterAsKernel]: never | undefined;
@@ -1493,6 +1497,14 @@ export interface IEventNamePropertyMapping {
14931497
* If `notebook = true`, this its telemetry for native editor/notebooks.
14941498
*/
14951499
[Telemetry.ExecuteCellPerceivedWarm]: undefined | { notebook: boolean };
1500+
/**
1501+
* Time take for jupyter server to start and be ready to run first user cell.
1502+
*/
1503+
[Telemetry.PerceivedJupyterStartupNotebook]: never | undefined;
1504+
/**
1505+
* 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.
1506+
*/
1507+
[Telemetry.StartExecuteNotebookCellPerceivedCold]: never | undefined;
14961508
[Telemetry.ExecuteNativeCell]: never | undefined;
14971509
[Telemetry.ExpandAll]: never | undefined;
14981510
[Telemetry.ExportNotebook]: never | undefined;

0 commit comments

Comments
 (0)