From fd41cda8127ea0d5f43d0fba6e058a2b324cce77 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Thu, 11 Jul 2024 12:46:29 +1000 Subject: [PATCH] Additional conda telemetry --- .../locators/common/nativePythonFinder.ts | 11 +++ .../composite/envsCollectionService.ts | 84 +++++++++++++++++-- .../common/environmentManagers/conda.ts | 4 + src/client/telemetry/index.ts | 32 +++++++ .../envsCollectionService.unit.test.ts | 4 + 5 files changed, 128 insertions(+), 7 deletions(-) diff --git a/src/client/pythonEnvironments/base/locators/common/nativePythonFinder.ts b/src/client/pythonEnvironments/base/locators/common/nativePythonFinder.ts index b8cb5c48a157..196808ac3e5f 100644 --- a/src/client/pythonEnvironments/base/locators/common/nativePythonFinder.ts +++ b/src/client/pythonEnvironments/base/locators/common/nativePythonFinder.ts @@ -47,10 +47,17 @@ export interface NativeEnvManagerInfo { version?: string; } +export type NativeCondaInfo = { + canSpawnConda: boolean; + condaRcs: string[]; + envDirs: string[]; +}; + export interface NativeGlobalPythonFinder extends Disposable { resolve(executable: string): Promise; refresh(): AsyncIterable; categoryToKind(category?: string): PythonEnvKind; + getCondaInfo(): Promise; } interface NativeLog { @@ -361,6 +368,10 @@ class NativeGlobalPythonFinderImpl extends DisposableBase implements NativeGloba this.outputChannel.error('Refresh error', ex); } } + + async getCondaInfo(): Promise { + return this.connection.sendRequest('condaInfo'); + } } type ConfigurationOptions = { diff --git a/src/client/pythonEnvironments/base/locators/composite/envsCollectionService.ts b/src/client/pythonEnvironments/base/locators/composite/envsCollectionService.ts index 00eec4866e78..266b2a4966cc 100644 --- a/src/client/pythonEnvironments/base/locators/composite/envsCollectionService.ts +++ b/src/client/pythonEnvironments/base/locators/composite/envsCollectionService.ts @@ -333,18 +333,30 @@ export class EnvsCollectionService extends PythonEnvsWatcher(); + await Promise.all( + // eslint-disable-next-line camelcase + [info?.rc_path, info?.user_rc_path, info?.sys_rc_path, ...(info?.config_files || [])].map( + async (rc) => { + if (rc && (await pathExists(rc))) { + condaRcFiles.add(rc); + } + }, + ), + ).catch(noop); + condaRcs = condaRcFiles.size; const duplicate = new Set(); Promise.all( (info?.envs || []).map(async (e) => { @@ -361,6 +373,13 @@ export class EnvsCollectionService extends PythonEnvsWatcher { + if (await pathExists(e)) { + condaInfoEnvsDirs += 1; + } + }), + ); nativeEnvs .filter((e) => this.nativeFinder.categoryToKind(e.kind) === PythonEnvKind.Conda) .forEach((e) => { @@ -368,9 +387,40 @@ export class EnvsCollectionService extends PythonEnvsWatcher e.executable.sysPrefix.toLowerCase() === rootPrefix && e.kind === PythonEnvKind.Conda, + ) + ) { + condaRootPrefixFoundInInfoNotInNative = nativeEnvs.some( + (e) => e.prefix?.toLowerCase() === rootPrefix.toLowerCase(), + ); + } + } + // eslint-disable-next-line camelcase + const defaultPrefix = (info?.default_prefix || '').toLowerCase(); + if (rootPrefix) { + // Check if we have a conda env that matches this prefix. + if ( + envs.some( + (e) => e.executable.sysPrefix.toLowerCase() === defaultPrefix && e.kind === PythonEnvKind.Conda, + ) + ) { + condaDefaultPrefixFoundInInfoNotInNative = nativeEnvs.some( + (e) => e.prefix?.toLowerCase() === defaultPrefix.toLowerCase(), + ); + } + } } catch (ex) { canSpawnConda = false; } + const nativeCondaInfoPromise = this.nativeFinder.getCondaInfo(); const prefixesSeenAlready = new Set(); await Promise.all( envs.map(async (env) => { @@ -480,6 +530,22 @@ export class EnvsCollectionService extends PythonEnvsWatcher traceError('Failed to send telemetry for missing environments', ex)); + const nativeCondaInfo = await nativeCondaInfoPromise.catch((ex) => + traceError(`Failed to get conda info from native locator`, ex), + ); + + type CondaTelemetry = { + nativeCanSpawnConda?: boolean; + nativeCondaInfoEnvsDirs?: number; + nativeCondaRcs?: number; + }; + + const condaTelemetry: CondaTelemetry = {}; + if (nativeCondaInfo) { + condaTelemetry.nativeCanSpawnConda = nativeCondaInfo.canSpawnConda; + condaTelemetry.nativeCondaInfoEnvsDirs = new Set(nativeCondaInfo.envDirs).size; + condaTelemetry.nativeCondaRcs = new Set(nativeCondaInfo.condaRcs).size; + } const environmentsWithoutPython = envs.filter( (e) => getEnvPath(e.executable.filename, e.location).pathType === 'envFolderPath', ).length; @@ -513,7 +579,7 @@ export class EnvsCollectionService extends PythonEnvsWatcher { + throw new Error('Method not implemented.'); + } + categoryToKind(_category: string): PythonEnvKind { throw new Error('Method not implemented.'); }