Skip to content

Commit 5e57d67

Browse files
committed
feat: enhance environment discovery logging and troubleshooting guidance
1 parent f983b64 commit 5e57d67

File tree

4 files changed

+77
-5
lines changed

4 files changed

+77
-5
lines changed

src/common/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export const ENVS_EXTENSION_ID = 'ms-python.vscode-python-envs';
44
export const PYTHON_EXTENSION_ID = 'ms-python.python';
55
export const JUPYTER_EXTENSION_ID = 'ms-toolsai.jupyter';
66
export const EXTENSION_ROOT_DIR = path.dirname(__dirname);
7+
export const ISSUES_URL = 'https://github.com/microsoft/vscode-python-environments/issues';
78

89
export const DEFAULT_PACKAGE_MANAGER_ID = 'ms-python.python:pip';
910
export const DEFAULT_ENV_MANAGER_ID = 'ms-python.python:venv';

src/common/telemetry/helpers.ts

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { getDefaultEnvManagerSetting, getDefaultPkgManagerSetting } from '../../features/settings/settingHelpers';
22
import { EnvironmentManagers, PythonProjectManager } from '../../internal.api';
3+
import { ISSUES_URL } from '../constants';
4+
import { traceInfo, traceWarn } from '../logging';
35
import { getWorkspaceFolders } from '../workspace.apis';
46
import { EventNames } from './constants';
57
import { sendTelemetryEvent } from './sender';
@@ -58,7 +60,7 @@ export async function sendProjectStructureTelemetry(
5860
for (const wsFolder of workspaceFolders) {
5961
const workspacePath = wsFolder.uri.fsPath;
6062
const projectPath = project.uri.fsPath;
61-
63+
6264
// Check if project is a subdirectory of workspace folder:
6365
// - Path must start with workspace path
6466
// - Path must not be equal to workspace path
@@ -80,3 +82,41 @@ export async function sendProjectStructureTelemetry(
8082
projectUnderRoot,
8183
});
8284
}
85+
86+
/**
87+
* Logs a summary of environment discovery results after startup.
88+
* If no environments are found, logs guidance to help users troubleshoot.
89+
*/
90+
export async function logDiscoverySummary(envManagers: EnvironmentManagers): Promise<void> {
91+
const managers = envManagers.managers;
92+
let totalEnvCount = 0;
93+
const managerSummaries: string[] = [];
94+
95+
for (const manager of managers) {
96+
try {
97+
const envs = await manager.getEnvironments('all');
98+
totalEnvCount += envs.length;
99+
if (envs.length > 0) {
100+
managerSummaries.push(`${manager.displayName}: ${envs.length}`);
101+
}
102+
} catch {
103+
// Discovery errors are already logged by InternalEnvironmentManager.refresh()
104+
}
105+
}
106+
107+
if (totalEnvCount === 0) {
108+
traceWarn(
109+
`No Python environments were found.\n` +
110+
` This may cause issues with Python tooling in VS Code.\n` +
111+
` Troubleshooting:\n` +
112+
` - Ensure Python is installed and on your PATH\n` +
113+
` - Check if your virtual environment has an 'activate' script\n` +
114+
` - Try running "Python Environments: Refresh All Environment Managers"\n` +
115+
` If environments should be detected, please report this: ${ISSUES_URL}/new`,
116+
);
117+
} else {
118+
traceInfo(
119+
`Environment discovery complete: ${totalEnvCount} environments found (${managerSummaries.join(', ')})`,
120+
);
121+
}
122+
}

src/extension.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ import { clearPersistentState, setPersistentState } from './common/persistentSta
1717
import { newProjectSelection } from './common/pickers/managers';
1818
import { StopWatch } from './common/stopWatch';
1919
import { EventNames } from './common/telemetry/constants';
20-
import { sendManagerSelectionTelemetry, sendProjectStructureTelemetry } from './common/telemetry/helpers';
20+
import {
21+
logDiscoverySummary,
22+
sendManagerSelectionTelemetry,
23+
sendProjectStructureTelemetry,
24+
} from './common/telemetry/helpers';
2125
import { sendTelemetryEvent } from './common/telemetry/sender';
2226
import { createDeferred } from './common/utils/deferred';
2327

@@ -545,6 +549,9 @@ export async function activate(context: ExtensionContext): Promise<PythonEnviron
545549
await terminalManager.initialize(api);
546550
sendManagerSelectionTelemetry(projectManager);
547551
await sendProjectStructureTelemetry(projectManager, envManagers);
552+
553+
// Log discovery summary to help users troubleshoot environment detection issues
554+
await logDiscoverySummary(envManagers);
548555
} catch (error) {
549556
traceError('Failed to initialize environment managers:', error);
550557
// Show a user-friendly error message

src/internal.api.ts

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ import {
2727
ResolveEnvironmentContext,
2828
SetEnvironmentScope,
2929
} from './api';
30+
import { ISSUES_URL } from './common/constants';
3031
import { CreateEnvironmentNotSupported, RemoveEnvironmentNotSupported } from './common/errors/NotSupportedError';
32+
import { traceWarn } from './common/logging';
3133
import { StopWatch } from './common/stopWatch';
3234
import { EventNames } from './common/telemetry/constants';
3335
import { sendTelemetryEvent } from './common/telemetry/sender';
@@ -204,26 +206,48 @@ export class InternalEnvironmentManager implements EnvironmentManager {
204206

205207
async refresh(options: RefreshEnvironmentsScope): Promise<void> {
206208
const sw = new StopWatch();
209+
const SLOW_DISCOVERY_THRESHOLD_MS = 15000;
207210
try {
208211
await this.manager.refresh(options);
209212
const envs = await this.manager.getEnvironments('all').catch(() => []);
210-
sendTelemetryEvent(EventNames.ENVIRONMENT_DISCOVERY, sw.elapsedTime, {
213+
const duration = sw.elapsedTime;
214+
sendTelemetryEvent(EventNames.ENVIRONMENT_DISCOVERY, duration, {
211215
managerId: this.id,
212216
result: 'success',
213217
envCount: envs.length,
214218
});
219+
220+
// Log warning for slow discovery
221+
if (duration > SLOW_DISCOVERY_THRESHOLD_MS) {
222+
traceWarn(
223+
`[${this.displayName}] Environment discovery took ${(duration / 1000).toFixed(1)}s (found ${envs.length} environments). ` +
224+
`If this is causing problems, please report it: ${ISSUES_URL}/new`,
225+
);
226+
}
215227
} catch (ex) {
228+
const duration = sw.elapsedTime;
216229
const isTimeout = ex instanceof Error && ex.message.includes('timed out');
230+
const errorType = ex instanceof Error ? ex.name : 'unknown';
217231
sendTelemetryEvent(
218232
EventNames.ENVIRONMENT_DISCOVERY,
219-
sw.elapsedTime,
233+
duration,
220234
{
221235
managerId: this.id,
222236
result: isTimeout ? 'timeout' : 'error',
223-
errorType: ex instanceof Error ? ex.name : 'unknown',
237+
errorType,
224238
},
225239
ex instanceof Error ? ex : undefined,
226240
);
241+
242+
// Log verbose failure message to help users report issues
243+
const errorMessage = ex instanceof Error ? ex.message : String(ex);
244+
traceWarn(
245+
`[${this.displayName}] Environment discovery failed after ${(duration / 1000).toFixed(1)}s.\n` +
246+
` Error: ${errorType} - ${errorMessage}\n` +
247+
` If environments are not being detected correctly, please report this issue:\n` +
248+
` ${ISSUES_URL}/new`,
249+
);
250+
227251
throw ex;
228252
}
229253
}

0 commit comments

Comments
 (0)