diff --git a/src/common/constants.ts b/src/common/constants.ts index a804df6e..80de2b54 100644 --- a/src/common/constants.ts +++ b/src/common/constants.ts @@ -4,6 +4,7 @@ export const ENVS_EXTENSION_ID = 'ms-python.vscode-python-envs'; export const PYTHON_EXTENSION_ID = 'ms-python.python'; export const JUPYTER_EXTENSION_ID = 'ms-toolsai.jupyter'; export const EXTENSION_ROOT_DIR = path.dirname(__dirname); +export const ISSUES_URL = 'https://github.com/microsoft/vscode-python-environments/issues'; export const DEFAULT_PACKAGE_MANAGER_ID = 'ms-python.python:pip'; export const DEFAULT_ENV_MANAGER_ID = 'ms-python.python:venv'; diff --git a/src/common/telemetry/helpers.ts b/src/common/telemetry/helpers.ts index 88382b6a..6e4e2e1b 100644 --- a/src/common/telemetry/helpers.ts +++ b/src/common/telemetry/helpers.ts @@ -1,7 +1,8 @@ import { getDefaultEnvManagerSetting, getDefaultPkgManagerSetting } from '../../features/settings/settingHelpers'; import { EnvironmentManagers, PythonProjectManager } from '../../internal.api'; import { getUvEnvironments } from '../../managers/builtin/uvEnvironments'; -import { traceVerbose } from '../logging'; +import { ISSUES_URL } from '../constants'; +import { traceInfo, traceVerbose, traceWarn } from '../logging'; import { getWorkspaceFolders } from '../workspace.apis'; import { EventNames } from './constants'; import { sendTelemetryEvent } from './sender'; @@ -154,3 +155,37 @@ export async function sendEnvironmentToolUsageTelemetry( traceVerbose('Failed to send environment tool usage telemetry:', error); } } + +/** + * Logs a summary of environment discovery results after startup. + * If no environments are found, logs guidance to help users troubleshoot. + */ +export async function logDiscoverySummary(envManagers: EnvironmentManagers): Promise { + const managers = envManagers.managers; + let totalEnvCount = 0; + const managerSummaries: string[] = []; + + for (const manager of managers) { + try { + const envs = await manager.getEnvironments('all'); + totalEnvCount += envs.length; + if (envs.length > 0) { + managerSummaries.push(`${manager.displayName}: ${envs.length}`); + } + } catch { + // Discovery errors are already logged by InternalEnvironmentManager.refresh() + } + } + + if (totalEnvCount === 0) { + traceWarn( + `No Python environments were found. ` + + `Try running "Python Environments: Run Python Environment Tool (PET) in Terminal..." from the Command Palette to diagnose. ` + + `If environments should be detected, please report this: ${ISSUES_URL}/new`, + ); + } else { + traceInfo( + `Environment discovery complete: ${totalEnvCount} environments found (${managerSummaries.join(', ')})`, + ); + } +} diff --git a/src/extension.ts b/src/extension.ts index c542fdbe..7f31fc07 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -18,6 +18,7 @@ import { newProjectSelection } from './common/pickers/managers'; import { StopWatch } from './common/stopWatch'; import { EventNames } from './common/telemetry/constants'; import { + logDiscoverySummary, sendEnvironmentToolUsageTelemetry, sendManagerSelectionTelemetry, sendProjectStructureTelemetry, @@ -550,6 +551,9 @@ export async function activate(context: ExtensionContext): Promise { const sw = new StopWatch(); + const SLOW_DISCOVERY_THRESHOLD_MS = 15000; try { await this.manager.refresh(options); const envs = await this.manager.getEnvironments('all').catch(() => []); - sendTelemetryEvent(EventNames.ENVIRONMENT_DISCOVERY, sw.elapsedTime, { + const duration = sw.elapsedTime; + sendTelemetryEvent(EventNames.ENVIRONMENT_DISCOVERY, duration, { managerId: this.id, result: 'success', envCount: envs.length, }); + + // Log warning for slow discovery + if (duration > SLOW_DISCOVERY_THRESHOLD_MS) { + traceWarn( + `[${this.displayName}] Environment discovery took ${(duration / 1000).toFixed(1)}s (found ${envs.length} environments). ` + + `If this is causing problems, please report it: ${ISSUES_URL}/new`, + ); + } } catch (ex) { + const duration = sw.elapsedTime; const isTimeout = ex instanceof Error && ex.message.includes('timed out'); + const errorType = ex instanceof Error ? ex.name : 'unknown'; sendTelemetryEvent( EventNames.ENVIRONMENT_DISCOVERY, - sw.elapsedTime, + duration, { managerId: this.id, result: isTimeout ? 'timeout' : 'error', - errorType: ex instanceof Error ? ex.name : 'unknown', + errorType, }, ex instanceof Error ? ex : undefined, ); + + // Log verbose failure message to help users report issues + const errorMessage = ex instanceof Error ? ex.message : String(ex); + traceWarn( + `[${this.displayName}] Environment discovery failed after ${(duration / 1000).toFixed(1)}s.\n` + + ` Error: ${errorType} - ${errorMessage}\n` + + ` If environments are not being detected correctly, please report this issue:\n` + + ` ${ISSUES_URL}/new`, + ); + throw ex; } }