telemetry for lightbulb and move to code actions (#211323)

* first pass on new telemetry

* change click condition to when there are 2 or fewer code actions, list out the code actions

* remove excessive calls

* cleanup

* also log the code action providers

* change owner to me

* change title to provider
This commit is contained in:
Justin Chen 2024-04-25 18:16:45 +08:00 committed by GitHub
parent 84d2ef91c5
commit a8823c333e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 53 additions and 9 deletions

View file

@ -273,7 +273,7 @@ export async function applyCodeAction(
codeActionKind: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The kind (refactor, quickfix) of the applied code action' };
codeActionIsPreferred: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Was the code action marked as being a preferred action?' };
reason: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The kind of action used to trigger apply code action.' };
owner: 'mjbvz';
owner: 'justschen';
comment: 'Event used to gain insights into which code actions are being triggered';
};

View file

@ -39,6 +39,7 @@ import { registerThemingParticipant } from 'vs/platform/theme/common/themeServic
import { CodeActionAutoApply, CodeActionFilter, CodeActionItem, CodeActionKind, CodeActionSet, CodeActionTrigger, CodeActionTriggerSource } from 'vs/editor/contrib/codeAction/common/types';
import { CodeActionModel, CodeActionsState } from 'vs/editor/contrib/codeAction/browser/codeActionModel';
import { HierarchicalKind } from 'vs/base/common/hierarchicalKind';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
interface IActionShowOptions {
@ -79,6 +80,7 @@ export class CodeActionController extends Disposable implements IEditorContribut
@IConfigurationService private readonly _configurationService: IConfigurationService,
@IActionWidgetService private readonly _actionWidgetService: IActionWidgetService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@ITelemetryService private readonly _telemetryService: ITelemetryService
) {
super();
@ -105,6 +107,29 @@ export class CodeActionController extends Disposable implements IEditorContribut
}
private async showCodeActionsFromLightbulb(actions: CodeActionSet, at: IAnchor | IPosition): Promise<void> {
// Telemetry for showing code actions from lightbulb. Shows us how often it was clicked.
type ShowCodeActionListEvent = {
codeActionListLength: number;
codeActions: string[];
codeActionProviders: string[];
};
type ShowListEventClassification = {
codeActionListLength: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The length of the code action list from the lightbulb widget.' };
codeActions: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The title of code actions in this menu.' };
codeActionProviders: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The provider of code actions in this menu.' };
owner: 'justschen';
comment: 'Event used to gain insights into what code actions are being shown';
};
this._telemetryService.publicLog2<ShowCodeActionListEvent, ShowListEventClassification>('codeAction.showCodeActionsFromLightbulb', {
codeActionListLength: actions.validActions.length,
codeActions: actions.validActions.map(action => action.action.title),
codeActionProviders: actions.validActions.map(action => action.provider?.displayName ?? ''),
});
if (actions.allAIFixes && actions.validActions.length === 1) {
const actionItem = actions.validActions[0];
const command = actionItem.action.command;
@ -280,13 +305,32 @@ export class CodeActionController extends Disposable implements IEditorContribut
const delegate: IActionListDelegate<CodeActionItem> = {
onSelect: async (action: CodeActionItem, preview?: boolean) => {
this._applyCodeAction(action, /* retrigger */ true, !!preview, ApplyCodeActionReason.FromCodeActions);
this._actionWidgetService.hide();
this._applyCodeAction(action, /* retrigger */ true, !!preview, options.fromLightbulb ? ApplyCodeActionReason.FromAILightbulb : ApplyCodeActionReason.FromCodeActions);
this._actionWidgetService.hide(false);
currentDecorations.clear();
},
onHide: () => {
onHide: (didCancel?) => {
this._editor?.focus();
currentDecorations.clear();
// Telemetry for showing code actions here. only log on `showLightbulb`. Logs when code action list is quit out.
if (options.fromLightbulb && didCancel !== undefined) {
type ShowCodeActionListEvent = {
codeActionListLength: number;
didCancel: boolean;
};
type ShowListEventClassification = {
codeActionListLength: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The length of the code action list when quit out. Can be from any code action menu.' };
didCancel: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether the code action was cancelled or selected.' };
owner: 'justschen';
comment: 'Event used to gain insights into how many valid code actions are being shown';
};
this._telemetryService.publicLog2<ShowCodeActionListEvent, ShowListEventClassification>('codeAction.showCodeActionList.onHide', {
codeActionListLength: actions.validActions.length,
didCancel: didCancel,
});
}
},
onHover: async (action: CodeActionItem, token: CancellationToken) => {
if (token.isCancellationRequested) {

View file

@ -36,7 +36,7 @@ export interface IActionWidgetService {
show<T>(user: string, supportsPreview: boolean, items: readonly IActionListItem<T>[], delegate: IActionListDelegate<T>, anchor: IAnchor, container: HTMLElement | undefined, actionBarActions?: readonly IAction[]): void;
hide(): void;
hide(didCancel?: boolean): void;
readonly isVisible: boolean;
}
@ -87,8 +87,8 @@ class ActionWidgetService extends Disposable implements IActionWidgetService {
this._list?.value?.focusNext();
}
hide() {
this._list.value?.hide();
hide(didCancel?: boolean) {
this._list.value?.hide(didCancel);
this._list.clear();
}
@ -139,7 +139,7 @@ class ActionWidgetService extends Disposable implements IActionWidgetService {
widget.style.width = `${width}px`;
const focusTracker = renderDisposables.add(dom.trackFocus(element));
renderDisposables.add(focusTracker.onDidBlur(() => this.hide()));
renderDisposables.add(focusTracker.onDidBlur(() => this.hide(true)));
return renderDisposables;
}
@ -179,7 +179,7 @@ registerAction2(class extends Action2 {
}
run(accessor: ServicesAccessor): void {
accessor.get(IActionWidgetService).hide();
accessor.get(IActionWidgetService).hide(true);
}
});