Skip to content

Add telemetry to capture perceived time taken to start jupyter and run cell #10217

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

Merged
merged 2 commits into from
Feb 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions news/3 Code Health/10098.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Telemetry to capture connections to `localhost` using the connect to remote Jupyter server feature.
1 change: 1 addition & 0 deletions news/3 Code Health/10212.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Telemetry to capture perceived startup times of Jupyter and time to execute a cell.
3 changes: 3 additions & 0 deletions src/client/datascience/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ export enum Telemetry {
SubmitCellThroughInput = 'DATASCIENCE.SUBMITCELLFROMREPL',
ConnectLocalJupyter = 'DS_INTERNAL.CONNECTLOCALJUPYTER',
ConnectRemoteJupyter = 'DS_INTERNAL.CONNECTREMOTEJUPYTER',
ConnectRemoteJupyterViaLocalHost = 'DS_INTERNAL.CONNECTREMOTEJUPYTER_VIA_LOCALHOST',
ConnectFailedJupyter = 'DS_INTERNAL.CONNECTFAILEDJUPYTER',
ConnectRemoteFailedJupyter = 'DS_INTERNAL.CONNECTREMOTEFAILEDJUPYTER',
StartSessionFailedJupyter = 'DS_INTERNAL.START_SESSION_FAILED_JUPYTER',
Expand Down Expand Up @@ -227,6 +228,8 @@ export enum Telemetry {
ExecuteCell = 'DATASCIENCE.EXECUTE_CELL_TIME',
ExecuteCellPerceivedCold = 'DS_INTERNAL.EXECUTE_CELL_PERCEIVED_COLD',
ExecuteCellPerceivedWarm = 'DS_INTERNAL.EXECUTE_CELL_PERCEIVED_WARM',
PerceivedJupyterStartupNotebook = 'DS_INTERNAL.PERCEIVED_JUPYTER_STARTUP_NOTEBOOK',
StartExecuteNotebookCellPerceivedCold = 'DS_INTERNAL.START_EXECUTE_NOTEBOOK_CELL_PERCEIVED_COLD',
WebviewStartup = 'DS_INTERNAL.WEBVIEW_STARTUP',
VariableExplorerFetchTime = 'DS_INTERNAL.VARIABLE_EXPLORER_FETCH_TIME',
WebviewStyleUpdate = 'DS_INTERNAL.WEBVIEW_STYLE_UPDATE',
Expand Down
16 changes: 14 additions & 2 deletions src/client/datascience/interactive-common/interactiveBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import { IFileSystem } from '../../common/platform/types';
import { IConfigurationService, IDisposableRegistry, IExperimentsManager } from '../../common/types';
import { createDeferred, Deferred } from '../../common/utils/async';
import * as localize from '../../common/utils/localize';
import { StopWatch } from '../../common/utils/stopWatch';
import { IInterpreterService, PythonInterpreter } from '../../interpreter/contracts';
import { captureTelemetry, sendTelemetryEvent } from '../../telemetry';
import { generateCellRangesFromDocument } from '../cellFactory';
Expand Down Expand Up @@ -101,6 +102,7 @@ import { InteractiveWindowMessageListener } from './interactiveWindowMessageList
export abstract class InteractiveBase extends WebViewHost<IInteractiveWindowMapping> implements IInteractiveBase {
private unfinishedCells: ICell[] = [];
private restartingKernel: boolean = false;
private perceivedJupyterStartupTelemetryCaptured: boolean = false;
private potentiallyUnfinishedStatus: Disposable[] = [];
private addSysInfoPromise: Deferred<boolean> | undefined;
private _notebook: INotebook | undefined;
Expand Down Expand Up @@ -500,8 +502,9 @@ export abstract class InteractiveBase extends WebViewHost<IInteractiveWindowMapp
debug?: boolean
): Promise<boolean> {
traceInfo(`Submitting code for ${this.id}`);
const stopWatch =
this._notebook && !this.perceivedJupyterStartupTelemetryCaptured ? new StopWatch() : undefined;
let result = true;

// Do not execute or render empty code cells
const cellMatcher = new CellMatcher(this.configService.getSettings().datascience);
if (cellMatcher.stripFirstMarker(code).length === 0) {
Expand Down Expand Up @@ -568,7 +571,16 @@ export abstract class InteractiveBase extends WebViewHost<IInteractiveWindowMapp
true
);
}

if (stopWatch && !this.perceivedJupyterStartupTelemetryCaptured) {
this.perceivedJupyterStartupTelemetryCaptured = true;
sendTelemetryEvent(Telemetry.PerceivedJupyterStartupNotebook, stopWatch?.elapsedTime);
const disposable = this._notebook.onSessionStatusChanged(e => {
if (e === ServerStatus.Busy) {
sendTelemetryEvent(Telemetry.StartExecuteNotebookCellPerceivedCold, stopWatch?.elapsedTime);
disposable.dispose();
}
});
}
const observable = this._notebook.executeObservable(code, file, line, id, false);

// Indicate we executed some code
Expand Down
6 changes: 6 additions & 0 deletions src/client/datascience/jupyter/jupyterExecution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ import { JupyterWaitForIdleError } from './jupyterWaitForIdleError';
import { KernelSelector, KernelSpecInterpreter } from './kernels/kernelSelector';
import { NotebookStarter } from './notebookStarter';

const LocalHosts = ['localhost', '127.0.0.1', '::1'];

export class JupyterExecutionBase implements IJupyterExecution {
private usablePythonInterpreter: PythonInterpreter | undefined;
private eventEmitter: EventEmitter<void> = new EventEmitter<void>();
Expand Down Expand Up @@ -159,6 +161,10 @@ export class JupyterExecutionBase implements IJupyterExecution {
this.startOrConnect(options, cancelToken),
kernelSpecInterpreterPromise
]);

if (!connection.localLaunch && LocalHosts.includes(connection.hostName.toLowerCase())) {
sendTelemetryEvent(Telemetry.ConnectRemoteJupyterViaLocalHost);
}
// Create a server tha t we will then attempt to connect to.
result = this.serviceContainer.get<INotebookServer>(INotebookServer);

Expand Down
12 changes: 12 additions & 0 deletions src/client/telemetry/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1460,6 +1460,10 @@ export interface IEventNamePropertyMapping {
[Telemetry.ConnectFailedJupyter]: never | undefined;
[Telemetry.ConnectLocalJupyter]: never | undefined;
[Telemetry.ConnectRemoteJupyter]: never | undefined;
/**
* Connecting to an existing Jupyter server, but connecting to localhost.
*/
[Telemetry.ConnectRemoteJupyterViaLocalHost]: never | undefined;
[Telemetry.ConnectRemoteFailedJupyter]: never | undefined;
[Telemetry.ConnectRemoteSelfCertFailedJupyter]: never | undefined;
[Telemetry.RegisterAndUseInterpreterAsKernel]: never | undefined;
Expand Down Expand Up @@ -1493,6 +1497,14 @@ export interface IEventNamePropertyMapping {
* If `notebook = true`, this its telemetry for native editor/notebooks.
*/
[Telemetry.ExecuteCellPerceivedWarm]: undefined | { notebook: boolean };
/**
* Time take for jupyter server to start and be ready to run first user cell.
*/
[Telemetry.PerceivedJupyterStartupNotebook]: never | undefined;
/**
* 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.
*/
[Telemetry.StartExecuteNotebookCellPerceivedCold]: never | undefined;
[Telemetry.ExecuteNativeCell]: never | undefined;
[Telemetry.ExpandAll]: never | undefined;
[Telemetry.ExportNotebook]: never | undefined;
Expand Down