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
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