Skip to content

Commit 7066f82

Browse files
authored
Capture count of envs collected (#23471)
1 parent deae60a commit 7066f82

File tree

6 files changed

+278
-18
lines changed

6 files changed

+278
-18
lines changed

src/client/pythonEnvironments/base/locators/composite/envsCollectionService.ts

+43-5
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { traceError, traceInfo, traceVerbose } from '../../../../logging';
99
import { sendTelemetryEvent } from '../../../../telemetry';
1010
import { EventName } from '../../../../telemetry/constants';
1111
import { normalizePath } from '../../../common/externalDependencies';
12-
import { PythonEnvInfo } from '../../info';
12+
import { PythonEnvInfo, PythonEnvKind } from '../../info';
1313
import { getEnvPath } from '../../info/env';
1414
import {
1515
GetRefreshEnvironmentsOptions,
@@ -54,7 +54,11 @@ export class EnvsCollectionService extends PythonEnvsWatcher<PythonEnvCollection
5454
return this.progressPromises.get(stage)?.promise;
5555
}
5656

57-
constructor(private readonly cache: IEnvsCollectionCache, private readonly locator: IResolvingLocator) {
57+
constructor(
58+
private readonly cache: IEnvsCollectionCache,
59+
private readonly locator: IResolvingLocator,
60+
private readonly usingNativeLocator: boolean,
61+
) {
5862
super();
5963
this.locator.onChanged((event) => {
6064
const query: PythonLocatorQuery | undefined = event.providerId
@@ -258,12 +262,46 @@ export class EnvsCollectionService extends PythonEnvsWatcher<PythonEnvCollection
258262

259263
private sendTelemetry(query: PythonLocatorQuery | undefined, stopWatch: StopWatch) {
260264
if (!query && !this.hasRefreshFinished(query)) {
265+
const envs = this.cache.getAllEnvs();
266+
const environmentsWithoutPython = envs.filter(
267+
(e) => getEnvPath(e.executable.filename, e.location).pathType === 'envFolderPath',
268+
).length;
269+
const activeStateEnvs = envs.filter((e) => e.kind === PythonEnvKind.ActiveState).length;
270+
const condaEnvs = envs.filter((e) => e.kind === PythonEnvKind.Conda).length;
271+
const customEnvs = envs.filter((e) => e.kind === PythonEnvKind.Custom).length;
272+
const hatchEnvs = envs.filter((e) => e.kind === PythonEnvKind.Hatch).length;
273+
const microsoftStoreEnvs = envs.filter((e) => e.kind === PythonEnvKind.MicrosoftStore).length;
274+
const otherGlobalEnvs = envs.filter((e) => e.kind === PythonEnvKind.OtherGlobal).length;
275+
const otherVirtualEnvs = envs.filter((e) => e.kind === PythonEnvKind.OtherVirtual).length;
276+
const pipEnvEnvs = envs.filter((e) => e.kind === PythonEnvKind.Pipenv).length;
277+
const poetryEnvs = envs.filter((e) => e.kind === PythonEnvKind.Poetry).length;
278+
const pyenvEnvs = envs.filter((e) => e.kind === PythonEnvKind.Pyenv).length;
279+
const systemEnvs = envs.filter((e) => e.kind === PythonEnvKind.System).length;
280+
const unknownEnvs = envs.filter((e) => e.kind === PythonEnvKind.Unknown).length;
281+
const venvEnvs = envs.filter((e) => e.kind === PythonEnvKind.Venv).length;
282+
const virtualEnvEnvs = envs.filter((e) => e.kind === PythonEnvKind.VirtualEnv).length;
283+
const virtualEnvWrapperEnvs = envs.filter((e) => e.kind === PythonEnvKind.VirtualEnvWrapper).length;
284+
261285
// Intent is to capture time taken for discovery of all envs to complete the first time.
262286
sendTelemetryEvent(EventName.PYTHON_INTERPRETER_DISCOVERY, stopWatch.elapsedTime, {
263287
interpreters: this.cache.getAllEnvs().length,
264-
environmentsWithoutPython: this.cache
265-
.getAllEnvs()
266-
.filter((e) => getEnvPath(e.executable.filename, e.location).pathType === 'envFolderPath').length,
288+
usingNativeLocator: this.usingNativeLocator,
289+
environmentsWithoutPython,
290+
activeStateEnvs,
291+
condaEnvs,
292+
customEnvs,
293+
hatchEnvs,
294+
microsoftStoreEnvs,
295+
otherGlobalEnvs,
296+
otherVirtualEnvs,
297+
pipEnvEnvs,
298+
poetryEnvs,
299+
pyenvEnvs,
300+
systemEnvs,
301+
unknownEnvs,
302+
venvEnvs,
303+
virtualEnvEnvs,
304+
virtualEnvWrapperEnvs,
267305
});
268306
}
269307
this.hasRefreshFinishedForQuery.set(query, true);

src/client/pythonEnvironments/base/locators/lowLevel/nativeLocator.ts

+45
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import {
1818
} from '../common/nativePythonFinder';
1919
import { disposeAll } from '../../../../common/utils/resourceLifecycle';
2020
import { StopWatch } from '../../../../common/utils/stopWatch';
21+
import { sendTelemetryEvent } from '../../../../telemetry';
22+
import { EventName } from '../../../../telemetry/constants';
2123

2224
function categoryToKind(category: string): PythonEnvKind {
2325
switch (category.toLowerCase()) {
@@ -106,6 +108,7 @@ export class NativeLocator implements ILocator<BasicEnvInfo>, IDisposable {
106108
const disposable = new Disposable(() => disposeAll(disposables));
107109
this.disposables.push(disposable);
108110
promise.finally(() => disposable.dispose());
111+
let environmentsWithoutPython = 0;
109112
disposables.push(
110113
this.finder.onDidFindPythonEnvironment((data: NativeEnvInfo) => {
111114
// TODO: What if executable is undefined?
@@ -121,6 +124,8 @@ export class NativeLocator implements ILocator<BasicEnvInfo>, IDisposable {
121124
searchLocation: data.projectPath ? Uri.file(data.projectPath) : undefined,
122125
identifiedUsingNativeLocator: true,
123126
});
127+
} else {
128+
environmentsWithoutPython += 1;
124129
}
125130
}),
126131
this.finder.onDidFindEnvironmentManager((data: NativeEnvManagerInfo) => {
@@ -147,6 +152,7 @@ export class NativeLocator implements ILocator<BasicEnvInfo>, IDisposable {
147152
`Finished searching for Python environments using Native Locator: ${stopWatch.elapsedTime} milliseconds`,
148153
);
149154
yield* envs;
155+
sendTelemetry(envs, environmentsWithoutPython, stopWatch);
150156
traceInfo(
151157
`Finished yielding Python environments using Native Locator: ${stopWatch.elapsedTime} milliseconds`,
152158
);
@@ -155,3 +161,42 @@ export class NativeLocator implements ILocator<BasicEnvInfo>, IDisposable {
155161
return iterator();
156162
}
157163
}
164+
165+
function sendTelemetry(envs: BasicEnvInfo[], environmentsWithoutPython: number, stopWatch: StopWatch) {
166+
const activeStateEnvs = envs.filter((e) => e.kind === PythonEnvKind.ActiveState).length;
167+
const condaEnvs = envs.filter((e) => e.kind === PythonEnvKind.Conda).length;
168+
const customEnvs = envs.filter((e) => e.kind === PythonEnvKind.Custom).length;
169+
const hatchEnvs = envs.filter((e) => e.kind === PythonEnvKind.Hatch).length;
170+
const microsoftStoreEnvs = envs.filter((e) => e.kind === PythonEnvKind.MicrosoftStore).length;
171+
const otherGlobalEnvs = envs.filter((e) => e.kind === PythonEnvKind.OtherGlobal).length;
172+
const otherVirtualEnvs = envs.filter((e) => e.kind === PythonEnvKind.OtherVirtual).length;
173+
const pipEnvEnvs = envs.filter((e) => e.kind === PythonEnvKind.Pipenv).length;
174+
const poetryEnvs = envs.filter((e) => e.kind === PythonEnvKind.Poetry).length;
175+
const pyenvEnvs = envs.filter((e) => e.kind === PythonEnvKind.Pyenv).length;
176+
const systemEnvs = envs.filter((e) => e.kind === PythonEnvKind.System).length;
177+
const unknownEnvs = envs.filter((e) => e.kind === PythonEnvKind.Unknown).length;
178+
const venvEnvs = envs.filter((e) => e.kind === PythonEnvKind.Venv).length;
179+
const virtualEnvEnvs = envs.filter((e) => e.kind === PythonEnvKind.VirtualEnv).length;
180+
const virtualEnvWrapperEnvs = envs.filter((e) => e.kind === PythonEnvKind.VirtualEnvWrapper).length;
181+
182+
// Intent is to capture time taken for discovery of all envs to complete the first time.
183+
sendTelemetryEvent(EventName.PYTHON_INTERPRETER_DISCOVERY, stopWatch.elapsedTime, {
184+
interpreters: envs.length,
185+
environmentsWithoutPython,
186+
activeStateEnvs,
187+
condaEnvs,
188+
customEnvs,
189+
hatchEnvs,
190+
microsoftStoreEnvs,
191+
otherGlobalEnvs,
192+
otherVirtualEnvs,
193+
pipEnvEnvs,
194+
poetryEnvs,
195+
pyenvEnvs,
196+
systemEnvs,
197+
unknownEnvs,
198+
venvEnvs,
199+
virtualEnvEnvs,
200+
virtualEnvWrapperEnvs,
201+
});
202+
}

src/client/pythonEnvironments/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ async function createLocator(
134134
await createCollectionCache(ext),
135135
// This is shared.
136136
resolvingLocator,
137+
useNativeLocator(),
137138
);
138139
return caching;
139140
}

src/client/telemetry/constants.ts

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export enum EventName {
1919
ENVIRONMENT_WITHOUT_PYTHON_SELECTED = 'ENVIRONMENT_WITHOUT_PYTHON_SELECTED',
2020
PYTHON_ENVIRONMENTS_API = 'PYTHON_ENVIRONMENTS_API',
2121
PYTHON_INTERPRETER_DISCOVERY = 'PYTHON_INTERPRETER_DISCOVERY',
22+
PYTHON_INTERPRETER_DISCOVERY_NATIVE = 'PYTHON_INTERPRETER_DISCOVERY_NATIVE',
2223
PYTHON_INTERPRETER_AUTO_SELECTION = 'PYTHON_INTERPRETER_AUTO_SELECTION',
2324
PYTHON_INTERPRETER_ACTIVATION_ENVIRONMENT_VARIABLES = 'PYTHON_INTERPRETER.ACTIVATION_ENVIRONMENT_VARIABLES',
2425
PYTHON_INTERPRETER_ACTIVATION_FOR_RUNNING_CODE = 'PYTHON_INTERPRETER_ACTIVATION_FOR_RUNNING_CODE',

src/client/telemetry/index.ts

+175
Original file line numberDiff line numberDiff line change
@@ -1144,9 +1144,124 @@ export interface IEventNamePropertyMapping {
11441144
"duration" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "karrtikr" },
11451145
"interpreters" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true , "owner": "karrtikr"},
11461146
"environmentsWithoutPython" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "karrtikr" }
1147+
"usingNativeLocator" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "owner": "donjayamanne" }
1148+
"activeStateEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1149+
"condaEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1150+
"customEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1151+
"hatchEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1152+
"microsoftStoreEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1153+
"otherGlobalEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1154+
"otherVirtualEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1155+
"pipEnvEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1156+
"poetryEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1157+
"pyenvEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1158+
"systemEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1159+
"unknownEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1160+
"venvEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1161+
"virtualEnvEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1162+
"virtualEnvWrapperEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
11471163
}
11481164
*/
11491165
[EventName.PYTHON_INTERPRETER_DISCOVERY]: {
1166+
/**
1167+
* The number of the interpreters discovered
1168+
*/
1169+
interpreters?: number;
1170+
/**
1171+
* Whether or not we're using the native locator.
1172+
*/
1173+
usingNativeLocator?: boolean;
1174+
/**
1175+
* The number of environments discovered not containing an interpreter
1176+
*/
1177+
environmentsWithoutPython?: number;
1178+
/**
1179+
* Number of environments of a specific type
1180+
*/
1181+
activeStateEnvs?: number;
1182+
/**
1183+
* Number of environments of a specific type
1184+
*/
1185+
condaEnvs?: number;
1186+
/**
1187+
* Number of environments of a specific type
1188+
*/
1189+
customEnvs?: number;
1190+
/**
1191+
* Number of environments of a specific type
1192+
*/
1193+
hatchEnvs?: number;
1194+
/**
1195+
* Number of environments of a specific type
1196+
*/
1197+
microsoftStoreEnvs?: number;
1198+
/**
1199+
* Number of environments of a specific type
1200+
*/
1201+
otherGlobalEnvs?: number;
1202+
/**
1203+
* Number of environments of a specific type
1204+
*/
1205+
otherVirtualEnvs?: number;
1206+
/**
1207+
* Number of environments of a specific type
1208+
*/
1209+
pipEnvEnvs?: number;
1210+
/**
1211+
* Number of environments of a specific type
1212+
*/
1213+
poetryEnvs?: number;
1214+
/**
1215+
* Number of environments of a specific type
1216+
*/
1217+
pyenvEnvs?: number;
1218+
/**
1219+
* Number of environments of a specific type
1220+
*/
1221+
systemEnvs?: number;
1222+
/**
1223+
* Number of environments of a specific type
1224+
*/
1225+
unknownEnvs?: number;
1226+
/**
1227+
* Number of environments of a specific type
1228+
*/
1229+
venvEnvs?: number;
1230+
/**
1231+
* Number of environments of a specific type
1232+
*/
1233+
virtualEnvEnvs?: number;
1234+
/**
1235+
* Number of environments of a specific type
1236+
*/
1237+
virtualEnvWrapperEnvs?: number;
1238+
};
1239+
/**
1240+
* Telemetry event sent when discovery of all python environments using the native locator(virtualenv, conda, pipenv etc.) finishes.
1241+
*/
1242+
/* __GDPR__
1243+
"python_interpreter_discovery_native" : {
1244+
"duration" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1245+
"interpreters" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true , "owner": "donjayamanne"},
1246+
"environmentsWithoutPython" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" }
1247+
"activeStateEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1248+
"condaEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1249+
"customEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1250+
"hatchEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1251+
"microsoftStoreEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1252+
"otherGlobalEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1253+
"otherVirtualEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1254+
"pipEnvEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1255+
"poetryEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1256+
"pyenvEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1257+
"systemEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1258+
"unknownEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1259+
"venvEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1260+
"virtualEnvEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1261+
"virtualEnvWrapperEnvs" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true, "owner": "donjayamanne" },
1262+
}
1263+
*/
1264+
[EventName.PYTHON_INTERPRETER_DISCOVERY_NATIVE]: {
11501265
/**
11511266
* The number of the interpreters discovered
11521267
*/
@@ -1155,6 +1270,66 @@ export interface IEventNamePropertyMapping {
11551270
* The number of environments discovered not containing an interpreter
11561271
*/
11571272
environmentsWithoutPython?: number;
1273+
/**
1274+
* Number of environments of a specific type
1275+
*/
1276+
activeStateEnvs?: number;
1277+
/**
1278+
* Number of environments of a specific type
1279+
*/
1280+
condaEnvs?: number;
1281+
/**
1282+
* Number of environments of a specific type
1283+
*/
1284+
customEnvs?: number;
1285+
/**
1286+
* Number of environments of a specific type
1287+
*/
1288+
hatchEnvs?: number;
1289+
/**
1290+
* Number of environments of a specific type
1291+
*/
1292+
microsoftStoreEnvs?: number;
1293+
/**
1294+
* Number of environments of a specific type
1295+
*/
1296+
otherGlobalEnvs?: number;
1297+
/**
1298+
* Number of environments of a specific type
1299+
*/
1300+
otherVirtualEnvs?: number;
1301+
/**
1302+
* Number of environments of a specific type
1303+
*/
1304+
pipEnvEnvs?: number;
1305+
/**
1306+
* Number of environments of a specific type
1307+
*/
1308+
poetryEnvs?: number;
1309+
/**
1310+
* Number of environments of a specific type
1311+
*/
1312+
pyenvEnvs?: number;
1313+
/**
1314+
* Number of environments of a specific type
1315+
*/
1316+
systemEnvs?: number;
1317+
/**
1318+
* Number of environments of a specific type
1319+
*/
1320+
unknownEnvs?: number;
1321+
/**
1322+
* Number of environments of a specific type
1323+
*/
1324+
venvEnvs?: number;
1325+
/**
1326+
* Number of environments of a specific type
1327+
*/
1328+
virtualEnvEnvs?: number;
1329+
/**
1330+
* Number of environments of a specific type
1331+
*/
1332+
virtualEnvWrapperEnvs?: number;
11581333
};
11591334
/**
11601335
* Telemetry event sent with details when user clicks the prompt with the following message:

0 commit comments

Comments
 (0)