Skip to content

Commit

Permalink
Modify telemetry to contain trigger time as property (#22941)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kartik Raj authored Feb 21, 2024
1 parent 178a0b2 commit ba94553
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/client/common/persistentState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export class PersistentState<T> implements IPersistentState<T> {
export const GLOBAL_PERSISTENT_KEYS_DEPRECATED = 'PYTHON_EXTENSION_GLOBAL_STORAGE_KEYS';
export const WORKSPACE_PERSISTENT_KEYS_DEPRECATED = 'PYTHON_EXTENSION_WORKSPACE_STORAGE_KEYS';

const GLOBAL_PERSISTENT_KEYS = 'PYTHON_GLOBAL_STORAGE_KEYS';
export const GLOBAL_PERSISTENT_KEYS = 'PYTHON_GLOBAL_STORAGE_KEYS';
const WORKSPACE_PERSISTENT_KEYS = 'PYTHON_WORKSPACE_STORAGE_KEYS';
type KeysStorageType = 'global' | 'workspace';
export type KeysStorage = { key: string; defaultValue: unknown };
Expand Down
6 changes: 4 additions & 2 deletions src/client/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import { WorkspaceService } from './common/application/workspace';
import { disposeAll } from './common/utils/resourceLifecycle';
import { ProposedExtensionAPI } from './proposedApiTypes';
import { buildProposedApi } from './proposedApi';
import { GLOBAL_PERSISTENT_KEYS } from './common/persistentState';

durations.codeLoadingTime = stopWatch.elapsedTime;

Expand All @@ -62,7 +63,9 @@ export async function activate(context: IExtensionContext): Promise<PythonExtens
let api: PythonExtension;
let ready: Promise<void>;
let serviceContainer: IServiceContainer;
let isFirstSession: boolean | undefined;
try {
isFirstSession = context.globalState.get(GLOBAL_PERSISTENT_KEYS, []).length === 0;
const workspaceService = new WorkspaceService();
context.subscriptions.push(
workspaceService.onDidGrantWorkspaceTrust(async () => {
Expand All @@ -79,8 +82,7 @@ export async function activate(context: IExtensionContext): Promise<PythonExtens
}
// Send the "success" telemetry only if activation did not fail.
// Otherwise Telemetry is send via the error handler.

sendStartupTelemetry(ready, durations, stopWatch, serviceContainer)
sendStartupTelemetry(ready, durations, stopWatch, serviceContainer, isFirstSession)
// Run in the background.
.ignoreErrors();
return api;
Expand Down
4 changes: 3 additions & 1 deletion src/client/languageServer/watcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,9 @@ export class LanguageServerWatcher implements IExtensionActivationService, ILang
// Start the language server.
if (startupStopWatch) {
// It means that startup is triggering this code, track time it takes since startup to activate this code.
sendTelemetryEvent(EventName.LANGUAGE_SERVER_TRIGGER_DURATION, startupStopWatch.elapsedTime);
sendTelemetryEvent(EventName.LANGUAGE_SERVER_TRIGGER_TIME, startupStopWatch.elapsedTime, {
triggerTime: startupStopWatch.elapsedTime,
});
}
await languageServerExtensionManager.startLanguageServer(lsResource, interpreter);

Expand Down
11 changes: 8 additions & 3 deletions src/client/startupTelemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export async function sendStartupTelemetry(
durations: IStartupDurations,
stopWatch: IStopWatch,
serviceContainer: IServiceContainer,
isFirstSession: boolean,
) {
if (isTestExecution()) {
return;
Expand All @@ -30,7 +31,7 @@ export async function sendStartupTelemetry(
try {
await activatedPromise;
durations.totalNonBlockingActivateTime = stopWatch.elapsedTime - durations.startActivateTime;
const props = await getActivationTelemetryProps(serviceContainer);
const props = await getActivationTelemetryProps(serviceContainer, isFirstSession);
sendTelemetryEvent(EventName.EDITOR_LOAD, durations, props);
} catch (ex) {
traceError('sendStartupTelemetry() failed.', ex);
Expand Down Expand Up @@ -76,7 +77,10 @@ export function hasUserDefinedPythonPath(resource: Resource, serviceContainer: I
: false;
}

async function getActivationTelemetryProps(serviceContainer: IServiceContainer): Promise<EditorLoadTelemetry> {
async function getActivationTelemetryProps(
serviceContainer: IServiceContainer,
isFirstSession?: boolean,
): Promise<EditorLoadTelemetry> {
// TODO: Not all of this data is showing up in the database...

// TODO: If any one of these parts fails we send no info. We should
Expand All @@ -88,7 +92,7 @@ async function getActivationTelemetryProps(serviceContainer: IServiceContainer):
const terminalHelper = serviceContainer.get<ITerminalHelper>(ITerminalHelper);
const terminalShellType = terminalHelper.identifyTerminalShell();
if (!workspaceService.isTrusted) {
return { workspaceFolderCount, terminal: terminalShellType };
return { workspaceFolderCount, terminal: terminalShellType, isFirstSession };
}
const interpreterService = serviceContainer.get<IInterpreterService>(IInterpreterService);
const mainWorkspaceUri = workspaceService.workspaceFolders?.length
Expand Down Expand Up @@ -132,5 +136,6 @@ async function getActivationTelemetryProps(serviceContainer: IServiceContainer):
usingUserDefinedInterpreter,
usingGlobalInterpreter,
appName,
isFirstSession,
};
}
2 changes: 1 addition & 1 deletion src/client/telemetry/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export enum EventName {
EXTENSION_SURVEY_PROMPT = 'EXTENSION_SURVEY_PROMPT',

LANGUAGE_SERVER_ENABLED = 'LANGUAGE_SERVER.ENABLED',
LANGUAGE_SERVER_TRIGGER_DURATION = 'LANGUAGE_SERVER.TRIGGER_DURATION',
LANGUAGE_SERVER_TRIGGER_TIME = 'LANGUAGE_SERVER_TRIGGER_TIME',
LANGUAGE_SERVER_STARTUP = 'LANGUAGE_SERVER.STARTUP',
LANGUAGE_SERVER_READY = 'LANGUAGE_SERVER.READY',
LANGUAGE_SERVER_TELEMETRY = 'LANGUAGE_SERVER.EVENT',
Expand Down
17 changes: 14 additions & 3 deletions src/client/telemetry/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,11 @@ export interface IEventNamePropertyMapping {
* If global interpreter is being used
*/
usingGlobalInterpreter?: boolean;
/**
* Carries `true` if it is the very first session of the user. We check whether persistent cache is empty
* to approximately guess if it's the first session.
*/
isFirstSession?: boolean;
};
/**
* Telemetry event sent when substituting Environment variables to calculate value of variables
Expand Down Expand Up @@ -1329,11 +1334,17 @@ export interface IEventNamePropertyMapping {
* Track how long it takes to trigger language server activation code, after Python extension starts activating.
*/
/* __GDPR__
"language_server_trigger_duration" : {
"duration" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "owner": "karrtikr", "isMeasurement": true }
"language_server_trigger_time" : {
"duration" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "karrtikr" },
"triggerTime" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "karrtikr" }
}
*/
[EventName.LANGUAGE_SERVER_TRIGGER_DURATION]: unknown;
[EventName.LANGUAGE_SERVER_TRIGGER_TIME]: {
/**
* Time it took to trigger language server startup.
*/
triggerTime: number;
};
/**
* Telemetry event sent when starting Node.js server
*/
Expand Down

0 comments on commit ba94553

Please sign in to comment.