Skip to content

Commit

Permalink
Capture count of envs collected (#23471)
Browse files Browse the repository at this point in the history
  • Loading branch information
DonJayamanne committed Jun 24, 2024
1 parent 86b9791 commit ed8fabf
Show file tree
Hide file tree
Showing 6 changed files with 278 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { traceError, traceInfo, traceVerbose } from '../../../../logging';
import { sendTelemetryEvent } from '../../../../telemetry';
import { EventName } from '../../../../telemetry/constants';
import { normalizePath } from '../../../common/externalDependencies';
import { PythonEnvInfo } from '../../info';
import { PythonEnvInfo, PythonEnvKind } from '../../info';
import { getEnvPath } from '../../info/env';
import {
GetRefreshEnvironmentsOptions,
Expand Down Expand Up @@ -54,7 +54,11 @@ export class EnvsCollectionService extends PythonEnvsWatcher<PythonEnvCollection
return this.progressPromises.get(stage)?.promise;
}

constructor(private readonly cache: IEnvsCollectionCache, private readonly locator: IResolvingLocator) {
constructor(
private readonly cache: IEnvsCollectionCache,
private readonly locator: IResolvingLocator,
private readonly usingNativeLocator: boolean,
) {
super();
this.locator.onChanged((event) => {
const query: PythonLocatorQuery | undefined = event.providerId
Expand Down Expand Up @@ -258,12 +262,46 @@ export class EnvsCollectionService extends PythonEnvsWatcher<PythonEnvCollection

private sendTelemetry(query: PythonLocatorQuery | undefined, stopWatch: StopWatch) {
if (!query && !this.hasRefreshFinished(query)) {
const envs = this.cache.getAllEnvs();
const environmentsWithoutPython = envs.filter(
(e) => getEnvPath(e.executable.filename, e.location).pathType === 'envFolderPath',
).length;
const activeStateEnvs = envs.filter((e) => e.kind === PythonEnvKind.ActiveState).length;
const condaEnvs = envs.filter((e) => e.kind === PythonEnvKind.Conda).length;
const customEnvs = envs.filter((e) => e.kind === PythonEnvKind.Custom).length;
const hatchEnvs = envs.filter((e) => e.kind === PythonEnvKind.Hatch).length;
const microsoftStoreEnvs = envs.filter((e) => e.kind === PythonEnvKind.MicrosoftStore).length;
const otherGlobalEnvs = envs.filter((e) => e.kind === PythonEnvKind.OtherGlobal).length;
const otherVirtualEnvs = envs.filter((e) => e.kind === PythonEnvKind.OtherVirtual).length;
const pipEnvEnvs = envs.filter((e) => e.kind === PythonEnvKind.Pipenv).length;
const poetryEnvs = envs.filter((e) => e.kind === PythonEnvKind.Poetry).length;
const pyenvEnvs = envs.filter((e) => e.kind === PythonEnvKind.Pyenv).length;
const systemEnvs = envs.filter((e) => e.kind === PythonEnvKind.System).length;
const unknownEnvs = envs.filter((e) => e.kind === PythonEnvKind.Unknown).length;
const venvEnvs = envs.filter((e) => e.kind === PythonEnvKind.Venv).length;
const virtualEnvEnvs = envs.filter((e) => e.kind === PythonEnvKind.VirtualEnv).length;
const virtualEnvWrapperEnvs = envs.filter((e) => e.kind === PythonEnvKind.VirtualEnvWrapper).length;

// Intent is to capture time taken for discovery of all envs to complete the first time.
sendTelemetryEvent(EventName.PYTHON_INTERPRETER_DISCOVERY, stopWatch.elapsedTime, {
interpreters: this.cache.getAllEnvs().length,
environmentsWithoutPython: this.cache
.getAllEnvs()
.filter((e) => getEnvPath(e.executable.filename, e.location).pathType === 'envFolderPath').length,
usingNativeLocator: this.usingNativeLocator,
environmentsWithoutPython,
activeStateEnvs,
condaEnvs,
customEnvs,
hatchEnvs,
microsoftStoreEnvs,
otherGlobalEnvs,
otherVirtualEnvs,
pipEnvEnvs,
poetryEnvs,
pyenvEnvs,
systemEnvs,
unknownEnvs,
venvEnvs,
virtualEnvEnvs,
virtualEnvWrapperEnvs,
});
}
this.hasRefreshFinishedForQuery.set(query, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import {
} from '../common/nativePythonFinder';
import { disposeAll } from '../../../../common/utils/resourceLifecycle';
import { StopWatch } from '../../../../common/utils/stopWatch';
import { sendTelemetryEvent } from '../../../../telemetry';
import { EventName } from '../../../../telemetry/constants';

function categoryToKind(category: string): PythonEnvKind {
switch (category.toLowerCase()) {
Expand Down Expand Up @@ -106,6 +108,7 @@ export class NativeLocator implements ILocator<BasicEnvInfo>, IDisposable {
const disposable = new Disposable(() => disposeAll(disposables));
this.disposables.push(disposable);
promise.finally(() => disposable.dispose());
let environmentsWithoutPython = 0;
disposables.push(
this.finder.onDidFindPythonEnvironment((data: NativeEnvInfo) => {
// TODO: What if executable is undefined?
Expand All @@ -121,6 +124,8 @@ export class NativeLocator implements ILocator<BasicEnvInfo>, IDisposable {
searchLocation: data.projectPath ? Uri.file(data.projectPath) : undefined,
identifiedUsingNativeLocator: true,
});
} else {
environmentsWithoutPython += 1;
}
}),
this.finder.onDidFindEnvironmentManager((data: NativeEnvManagerInfo) => {
Expand All @@ -147,6 +152,7 @@ export class NativeLocator implements ILocator<BasicEnvInfo>, IDisposable {
`Finished searching for Python environments using Native Locator: ${stopWatch.elapsedTime} milliseconds`,
);
yield* envs;
sendTelemetry(envs, environmentsWithoutPython, stopWatch);
traceInfo(
`Finished yielding Python environments using Native Locator: ${stopWatch.elapsedTime} milliseconds`,
);
Expand All @@ -155,3 +161,42 @@ export class NativeLocator implements ILocator<BasicEnvInfo>, IDisposable {
return iterator();
}
}

function sendTelemetry(envs: BasicEnvInfo[], environmentsWithoutPython: number, stopWatch: StopWatch) {
const activeStateEnvs = envs.filter((e) => e.kind === PythonEnvKind.ActiveState).length;
const condaEnvs = envs.filter((e) => e.kind === PythonEnvKind.Conda).length;
const customEnvs = envs.filter((e) => e.kind === PythonEnvKind.Custom).length;
const hatchEnvs = envs.filter((e) => e.kind === PythonEnvKind.Hatch).length;
const microsoftStoreEnvs = envs.filter((e) => e.kind === PythonEnvKind.MicrosoftStore).length;
const otherGlobalEnvs = envs.filter((e) => e.kind === PythonEnvKind.OtherGlobal).length;
const otherVirtualEnvs = envs.filter((e) => e.kind === PythonEnvKind.OtherVirtual).length;
const pipEnvEnvs = envs.filter((e) => e.kind === PythonEnvKind.Pipenv).length;
const poetryEnvs = envs.filter((e) => e.kind === PythonEnvKind.Poetry).length;
const pyenvEnvs = envs.filter((e) => e.kind === PythonEnvKind.Pyenv).length;
const systemEnvs = envs.filter((e) => e.kind === PythonEnvKind.System).length;
const unknownEnvs = envs.filter((e) => e.kind === PythonEnvKind.Unknown).length;
const venvEnvs = envs.filter((e) => e.kind === PythonEnvKind.Venv).length;
const virtualEnvEnvs = envs.filter((e) => e.kind === PythonEnvKind.VirtualEnv).length;
const virtualEnvWrapperEnvs = envs.filter((e) => e.kind === PythonEnvKind.VirtualEnvWrapper).length;

// Intent is to capture time taken for discovery of all envs to complete the first time.
sendTelemetryEvent(EventName.PYTHON_INTERPRETER_DISCOVERY, stopWatch.elapsedTime, {
interpreters: envs.length,
environmentsWithoutPython,
activeStateEnvs,
condaEnvs,
customEnvs,
hatchEnvs,
microsoftStoreEnvs,
otherGlobalEnvs,
otherVirtualEnvs,
pipEnvEnvs,
poetryEnvs,
pyenvEnvs,
systemEnvs,
unknownEnvs,
venvEnvs,
virtualEnvEnvs,
virtualEnvWrapperEnvs,
});
}
1 change: 1 addition & 0 deletions src/client/pythonEnvironments/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ async function createLocator(
await createCollectionCache(ext),
// This is shared.
resolvingLocator,
useNativeLocator(),
);
return caching;
}
Expand Down
1 change: 1 addition & 0 deletions src/client/telemetry/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export enum EventName {
ENVIRONMENT_WITHOUT_PYTHON_SELECTED = 'ENVIRONMENT_WITHOUT_PYTHON_SELECTED',
PYTHON_ENVIRONMENTS_API = 'PYTHON_ENVIRONMENTS_API',
PYTHON_INTERPRETER_DISCOVERY = 'PYTHON_INTERPRETER_DISCOVERY',
PYTHON_INTERPRETER_DISCOVERY_NATIVE = 'PYTHON_INTERPRETER_DISCOVERY_NATIVE',
PYTHON_INTERPRETER_AUTO_SELECTION = 'PYTHON_INTERPRETER_AUTO_SELECTION',
PYTHON_INTERPRETER_ACTIVATION_ENVIRONMENT_VARIABLES = 'PYTHON_INTERPRETER.ACTIVATION_ENVIRONMENT_VARIABLES',
PYTHON_INTERPRETER_ACTIVATION_FOR_RUNNING_CODE = 'PYTHON_INTERPRETER_ACTIVATION_FOR_RUNNING_CODE',
Expand Down
175 changes: 175 additions & 0 deletions src/client/telemetry/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1144,9 +1144,124 @@ export interface IEventNamePropertyMapping {
"duration" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "karrtikr" },
"interpreters" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true , "owner": "karrtikr"},
"environmentsWithoutPython" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "karrtikr" }
"usingNativeLocator" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "owner": "donjayamanne" }
"activeStateEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"condaEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"customEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"hatchEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"microsoftStoreEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"otherGlobalEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"otherVirtualEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"pipEnvEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"poetryEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"pyenvEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"systemEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"unknownEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"venvEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"virtualEnvEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"virtualEnvWrapperEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
}
*/
[EventName.PYTHON_INTERPRETER_DISCOVERY]: {
/**
* The number of the interpreters discovered
*/
interpreters?: number;
/**
* Whether or not we're using the native locator.
*/
usingNativeLocator?: boolean;
/**
* The number of environments discovered not containing an interpreter
*/
environmentsWithoutPython?: number;
/**
* Number of environments of a specific type
*/
activeStateEnvs?: number;
/**
* Number of environments of a specific type
*/
condaEnvs?: number;
/**
* Number of environments of a specific type
*/
customEnvs?: number;
/**
* Number of environments of a specific type
*/
hatchEnvs?: number;
/**
* Number of environments of a specific type
*/
microsoftStoreEnvs?: number;
/**
* Number of environments of a specific type
*/
otherGlobalEnvs?: number;
/**
* Number of environments of a specific type
*/
otherVirtualEnvs?: number;
/**
* Number of environments of a specific type
*/
pipEnvEnvs?: number;
/**
* Number of environments of a specific type
*/
poetryEnvs?: number;
/**
* Number of environments of a specific type
*/
pyenvEnvs?: number;
/**
* Number of environments of a specific type
*/
systemEnvs?: number;
/**
* Number of environments of a specific type
*/
unknownEnvs?: number;
/**
* Number of environments of a specific type
*/
venvEnvs?: number;
/**
* Number of environments of a specific type
*/
virtualEnvEnvs?: number;
/**
* Number of environments of a specific type
*/
virtualEnvWrapperEnvs?: number;
};
/**
* Telemetry event sent when discovery of all python environments using the native locator(virtualenv, conda, pipenv etc.) finishes.
*/
/* __GDPR__
"python_interpreter_discovery_native" : {
"duration" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"interpreters" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true , "owner": "donjayamanne"},
"environmentsWithoutPython" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" }
"activeStateEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"condaEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"customEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"hatchEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"microsoftStoreEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"otherGlobalEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"otherVirtualEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"pipEnvEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"poetryEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"pyenvEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"systemEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"unknownEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"venvEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"virtualEnvEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
"virtualEnvWrapperEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
}
*/
[EventName.PYTHON_INTERPRETER_DISCOVERY_NATIVE]: {
/**
* The number of the interpreters discovered
*/
Expand All @@ -1155,6 +1270,66 @@ export interface IEventNamePropertyMapping {
* The number of environments discovered not containing an interpreter
*/
environmentsWithoutPython?: number;
/**
* Number of environments of a specific type
*/
activeStateEnvs?: number;
/**
* Number of environments of a specific type
*/
condaEnvs?: number;
/**
* Number of environments of a specific type
*/
customEnvs?: number;
/**
* Number of environments of a specific type
*/
hatchEnvs?: number;
/**
* Number of environments of a specific type
*/
microsoftStoreEnvs?: number;
/**
* Number of environments of a specific type
*/
otherGlobalEnvs?: number;
/**
* Number of environments of a specific type
*/
otherVirtualEnvs?: number;
/**
* Number of environments of a specific type
*/
pipEnvEnvs?: number;
/**
* Number of environments of a specific type
*/
poetryEnvs?: number;
/**
* Number of environments of a specific type
*/
pyenvEnvs?: number;
/**
* Number of environments of a specific type
*/
systemEnvs?: number;
/**
* Number of environments of a specific type
*/
unknownEnvs?: number;
/**
* Number of environments of a specific type
*/
venvEnvs?: number;
/**
* Number of environments of a specific type
*/
virtualEnvEnvs?: number;
/**
* Number of environments of a specific type
*/
virtualEnvWrapperEnvs?: number;
};
/**
* Telemetry event sent with details when user clicks the prompt with the following message:
Expand Down
Loading

0 comments on commit ed8fabf

Please sign in to comment.