Skip to content

Commit f72b005

Browse files
committed
add telemetry for copy import path
1 parent 1e33952 commit f72b005

4 files changed

Lines changed: 53 additions & 18 deletions

File tree

src/client/application/importPath/copyImportPathCommand.ts

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { IExtensionSingleActivationService } from '../../activation/types';
77
import { Commands } from '../../common/constants';
88
import { getSysPath } from '../../common/utils/pythonUtils';
99
import { IInterpreterPathService } from '../../common/types';
10+
import { sendTelemetryEvent } from '../../telemetry';
11+
import { EventName } from '../../telemetry/constants';
1012

1113
@injectable()
1214
export class CopyImportPathCommand implements IExtensionSingleActivationService {
@@ -24,17 +26,42 @@ export class CopyImportPathCommand implements IExtensionSingleActivationService
2426
}
2527

2628
private async execute(fileUri?: vscode.Uri): Promise<void> {
27-
const uri = fileUri ?? vscode.window.activeTextEditor?.document.uri;
28-
if (!uri || !uri.fsPath.endsWith('.py')) {
29-
void vscode.window.showWarningMessage('No Python file selected for import-path copy.');
30-
return;
31-
}
29+
const trigger = fileUri ? 'api' : vscode.window.activeTextEditor ? 'contextMenu' : 'palette';
30+
let outcome: 'success' | 'noFile' | 'notPy' | 'error' = 'success';
31+
let strategy: 'sysPath' | 'workspace' | 'fallback' | undefined = undefined;
32+
let exObj: Error | undefined = undefined;
3233

33-
const resource: vscode.Uri | undefined = uri ?? this.workspace.workspaceFolders?.[0]?.uri;
34-
const pythonPath = this.interpreterPathService.get(resource);
35-
const importPath = this.resolveImportPath(uri.fsPath, pythonPath);
36-
await this.clipboard.writeText(importPath);
37-
void vscode.window.showInformationMessage(`Copied: ${importPath}`);
34+
try {
35+
const uri = fileUri ?? vscode.window.activeTextEditor?.document.uri;
36+
if (!uri) {
37+
outcome = 'noFile';
38+
return;
39+
}
40+
if (!uri.fsPath.endsWith('.py')) {
41+
outcome = 'notPy';
42+
return;
43+
}
44+
const resource = uri ?? this.workspace.workspaceFolders?.[0]?.uri;
45+
const pythonPath = this.interpreterPathService.get(resource);
46+
const [importPath, strat] = this.resolveImportPath(uri.fsPath, pythonPath);
47+
strategy = strat;
48+
await this.clipboard.writeText(importPath);
49+
void vscode.window.showInformationMessage(`Copied: ${importPath}`);
50+
} catch (ex) {
51+
outcome = 'error';
52+
exObj = ex as Error;
53+
} finally {
54+
sendTelemetryEvent(
55+
EventName.COPY_IMPORT_PATH,
56+
undefined,
57+
{
58+
trigger,
59+
outcome,
60+
strategy,
61+
},
62+
exObj,
63+
);
64+
}
3865
}
3966

4067
/**
@@ -46,25 +73,26 @@ export class CopyImportPathCommand implements IExtensionSingleActivationService
4673
* 2. If the file is located under the current workspace folder, the path relative to the workspace root is used.
4774
* 3. Otherwise, the import path falls back to the file name (without extension).
4875
*
49-
* @param absPath - The absolute path to a `.py` file.
50-
* @returns The resolved import path in dotted notation (e.g., 'pkg.module').
76+
* @param absPath Absolute path to a `.py` file.
77+
* @param pythonPath Optional Python interpreter path to determine `sys.path`.
78+
* @returns A tuple: [import path in dotted notation, resolution source: 'sysPath' | 'workspace' | 'fallback']
5179
*/
52-
private resolveImportPath(absPath: string, pythonPath?: string): string {
80+
private resolveImportPath(absPath: string, pythonPath?: string): [string, 'sysPath' | 'workspace' | 'fallback'] {
5381
// ---------- ① sys.path ----------
5482
for (const sysRoot of getSysPath(pythonPath)) {
5583
if (sysRoot && absPath.startsWith(sysRoot)) {
56-
return CopyImportPathCommand.toDotted(path.relative(sysRoot, absPath));
84+
return [CopyImportPathCommand.toDotted(path.relative(sysRoot, absPath)), 'sysPath'];
5785
}
5886
}
5987

60-
// ---------- ② workspaceFolder ----------
88+
// ---------- ② workspace ----------
6189
const ws = this.workspace.getWorkspaceFolder(vscode.Uri.file(absPath));
6290
if (ws && absPath.startsWith(ws.uri.fsPath)) {
63-
return CopyImportPathCommand.toDotted(path.relative(ws.uri.fsPath, absPath));
91+
return [CopyImportPathCommand.toDotted(path.relative(ws.uri.fsPath, absPath)), 'workspace'];
6492
}
6593

6694
// ---------- ③ fallback ----------
67-
return path.basename(absPath, '.py');
95+
return [path.basename(absPath, '.py'), 'fallback'];
6896
}
6997

7098
private static toDotted(relPath: string): string {

src/client/common/utils/pythonUtils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { execFileSync } from 'child_process';
2+
import { traceWarn } from '../../logging';
23

34
export function getSysPath(pythonCmd = 'python3'): string[] {
45
// cleanSysPathCommand removes the working directory from sys.path.
@@ -19,7 +20,7 @@ export function getSysPath(pythonCmd = 'python3'): string[] {
1920
});
2021
return JSON.parse(out);
2122
} catch (err) {
22-
console.warn('[CopyImportPath] getSysPath failed:', err);
23+
traceWarn('[CopyImportPath] getSysPath failed:', err);
2324
return [];
2425
}
2526
}

src/client/telemetry/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export enum EventName {
3737
ENVFILE_WORKSPACE = 'ENVFILE_WORKSPACE',
3838
EXECUTION_CODE = 'EXECUTION_CODE',
3939
EXECUTION_DJANGO = 'EXECUTION_DJANGO',
40+
COPY_IMPORT_PATH = 'COPY_IMPORT_PATH',
4041

4142
// Python testing specific telemetry
4243
UNITTEST_CONFIGURING = 'UNITTEST.CONFIGURING',

src/client/telemetry/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2458,4 +2458,9 @@ export interface IEventNamePropertyMapping {
24582458
"errortype": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "comment": "Type of error when calling TAS (ServerError, NoResponse, etc.)"}
24592459
}
24602460
*/
2461+
[EventName.COPY_IMPORT_PATH]: {
2462+
trigger: 'api' | 'contextMenu' | 'palette';
2463+
outcome: 'success' | 'noFile' | 'notPy' | 'error';
2464+
strategy?: 'sysPath' | 'workspace' | 'fallback';
2465+
};
24612466
}

0 commit comments

Comments
 (0)