Debug panel: Add telemetry and modal dialog for import error (#301190)

* telemetry and modal dialog

* Feedback updates
This commit is contained in:
Vijay Upadya
2026-03-12 12:19:52 -07:00
committed by GitHub
parent c11185fd50
commit e4a2b6b4e8

View File

@@ -11,9 +11,10 @@ import { localize, localize2 } from '../../../../../nls.js';
import { Action2, MenuId, registerAction2 } from '../../../../../platform/actions/common/actions.js'; import { Action2, MenuId, registerAction2 } from '../../../../../platform/actions/common/actions.js';
import { Categories } from '../../../../../platform/action/common/actionCommonCategories.js'; import { Categories } from '../../../../../platform/action/common/actionCommonCategories.js';
import { ContextKeyExpr } from '../../../../../platform/contextkey/common/contextkey.js'; import { ContextKeyExpr } from '../../../../../platform/contextkey/common/contextkey.js';
import { IFileDialogService } from '../../../../../platform/dialogs/common/dialogs.js'; import { IDialogService, IFileDialogService } from '../../../../../platform/dialogs/common/dialogs.js';
import { IFileService } from '../../../../../platform/files/common/files.js'; import { IFileService } from '../../../../../platform/files/common/files.js';
import { INotificationService, Severity } from '../../../../../platform/notification/common/notification.js'; import { INotificationService, Severity } from '../../../../../platform/notification/common/notification.js';
import { ITelemetryService } from '../../../../../platform/telemetry/common/telemetry.js';
import { ActiveEditorContext } from '../../../../common/contextkeys.js'; import { ActiveEditorContext } from '../../../../common/contextkeys.js';
import { IEditorService } from '../../../../services/editor/common/editorService.js'; import { IEditorService } from '../../../../services/editor/common/editorService.js';
import { isChatViewTitleActionContext } from '../../common/actions/chatActions.js'; import { isChatViewTitleActionContext } from '../../common/actions/chatActions.js';
@@ -126,6 +127,7 @@ export function registerChatOpenAgentDebugPanelAction() {
const fileDialogService = accessor.get(IFileDialogService); const fileDialogService = accessor.get(IFileDialogService);
const fileService = accessor.get(IFileService); const fileService = accessor.get(IFileService);
const notificationService = accessor.get(INotificationService); const notificationService = accessor.get(INotificationService);
const telemetryService = accessor.get(ITelemetryService);
const sessionResource = chatDebugService.activeSessionResource; const sessionResource = chatDebugService.activeSessionResource;
if (!sessionResource) { if (!sessionResource) {
@@ -146,6 +148,10 @@ export function registerChatOpenAgentDebugPanelAction() {
} }
await fileService.writeFile(outputPath, VSBuffer.wrap(data)); await fileService.writeFile(outputPath, VSBuffer.wrap(data));
telemetryService.publicLog2<ChatDebugExportEvent, ChatDebugExportClassification>('chatDebugLogExported', {
fileSizeBytes: data.byteLength,
});
} }
}); });
@@ -169,10 +175,12 @@ export function registerChatOpenAgentDebugPanelAction() {
async run(accessor: ServicesAccessor): Promise<void> { async run(accessor: ServicesAccessor): Promise<void> {
const chatDebugService = accessor.get(IChatDebugService); const chatDebugService = accessor.get(IChatDebugService);
const dialogService = accessor.get(IDialogService);
const editorService = accessor.get(IEditorService); const editorService = accessor.get(IEditorService);
const fileDialogService = accessor.get(IFileDialogService); const fileDialogService = accessor.get(IFileDialogService);
const fileService = accessor.get(IFileService); const fileService = accessor.get(IFileService);
const notificationService = accessor.get(INotificationService); const notificationService = accessor.get(INotificationService);
const telemetryService = accessor.get(ITelemetryService);
const defaultUri = joinPath(await fileDialogService.defaultFilePath(), defaultDebugLogFileName); const defaultUri = joinPath(await fileDialogService.defaultFilePath(), defaultDebugLogFileName);
const result = await fileDialogService.showOpenDialog({ const result = await fileDialogService.showOpenDialog({
@@ -187,19 +195,59 @@ export function registerChatOpenAgentDebugPanelAction() {
const maxImportSize = 50 * 1024 * 1024; // 50 MB const maxImportSize = 50 * 1024 * 1024; // 50 MB
const stat = await fileService.stat(result[0]); const stat = await fileService.stat(result[0]);
if (stat.size !== undefined && stat.size > maxImportSize) { if (stat.size !== undefined && stat.size > maxImportSize) {
notificationService.notify({ severity: Severity.Warning, message: localize('chatDebugLog.fileTooLarge', "The selected file exceeds the 50 MB size limit for log imports.") }); telemetryService.publicLog2<ChatDebugImportEvent, ChatDebugImportClassification>('chatDebugLogImported', {
fileSizeBytes: stat.size,
result: 'fileTooLarge',
});
await dialogService.warn(
localize('chatDebugLog.fileTooLargeTitle', "File Too Large"),
localize('chatDebugLog.fileTooLargeDetail', "The selected file ({0} MB) exceeds the 50 MB size limit for debug log imports.", (stat.size / (1024 * 1024)).toFixed(1))
);
return; return;
} }
const content = await fileService.readFile(result[0]); const content = await fileService.readFile(result[0]);
const sessionUri = await chatDebugService.importLog(content.value.buffer); const sessionUri = await chatDebugService.importLog(content.value.buffer);
if (!sessionUri) { if (!sessionUri) {
telemetryService.publicLog2<ChatDebugImportEvent, ChatDebugImportClassification>('chatDebugLogImported', {
fileSizeBytes: content.value.byteLength,
result: 'providerFailed',
});
notificationService.notify({ severity: Severity.Warning, message: localize('chatDebugLog.importFailed', "Import is not supported by the current provider.") }); notificationService.notify({ severity: Severity.Warning, message: localize('chatDebugLog.importFailed', "Import is not supported by the current provider.") });
return; return;
} }
telemetryService.publicLog2<ChatDebugImportEvent, ChatDebugImportClassification>('chatDebugLogImported', {
fileSizeBytes: content.value.byteLength,
result: 'success',
});
const options: IChatDebugEditorOptions = { pinned: true, sessionResource: sessionUri, viewHint: 'overview' }; const options: IChatDebugEditorOptions = { pinned: true, sessionResource: sessionUri, viewHint: 'overview' };
await editorService.openEditor(ChatDebugEditorInput.instance, options); await editorService.openEditor(ChatDebugEditorInput.instance, options);
} }
}); });
} }
// Telemetry types
type ChatDebugExportEvent = {
fileSizeBytes: number;
};
type ChatDebugExportClassification = {
fileSizeBytes: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; comment: 'Size of the exported chat debug log file in bytes.' };
owner: 'vijayu';
comment: 'Tracks usage of the debug panel export feature.';
};
type ChatDebugImportEvent = {
fileSizeBytes: number;
result: 'success' | 'fileTooLarge' | 'providerFailed';
};
type ChatDebugImportClassification = {
fileSizeBytes: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; comment: 'Size of the imported chat debug log file in bytes.' };
result: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Outcome of the chat debug file import: success, fileTooLarge, or providerFailed.' };
owner: 'vijayu';
comment: 'Tracks usage of the debug panel import feature and failure modes.';
};