Skip to content
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
([#10049](https://github.com/Microsoft/vscode-python/issues/10049))
1. Track cold/warm times to execute notebook cells.
([#10176](https://github.com/Microsoft/vscode-python/issues/10176))
1. Telemetry to capture connections to `localhost` using the connect to remote Jupyter server feature.
([#10098](https://github.com/Microsoft/vscode-python/issues/10098))
1. Telemetry to capture perceived startup times of Jupyter and time to execute a cell.
([#10212](https://github.com/Microsoft/vscode-python/issues/10212))

### Thanks

Expand Down
3 changes: 3 additions & 0 deletions src/client/datascience/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,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 @@ -209,6 +210,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
15 changes: 13 additions & 2 deletions src/client/datascience/interactive-common/interactiveBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,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 @@ -78,6 +79,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 @@ -457,8 +459,8 @@ export abstract class InteractiveBase extends WebViewHost<IInteractiveWindowMapp
// tslint:disable-next-line: max-func-body-length
protected async submitCode(code: string, file: string, line: number, id?: string, _editor?: TextEditor, 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 @@ -511,7 +513,16 @@ export abstract class InteractiveBase extends WebViewHost<IInteractiveWindowMapp
if (file !== Identifiers.EmptyFileName) {
await this._notebook.execute(`__file__ = '${file.replace(/\\/g, '\\\\')}'`, file, line, uuid(), undefined, 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
5 changes: 5 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 @@ -143,6 +145,9 @@ export class JupyterExecutionBase implements IJupyterExecution {
try {
// Start or connect to the process
[connection, kernelSpecInterpreter] = await Promise.all([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 @@ -1436,6 +1436,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 @@ -1469,6 +1473,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