Add telemetry reporting to rename suggestions (#205869)

rename suggestions: add telemetry reporting
This commit is contained in:
Ulugbek Abdullaev 2024-02-22 10:42:51 +01:00 committed by GitHub
parent a6ba9af63c
commit a4f9d32866
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 59 additions and 3 deletions

View file

@ -36,7 +36,8 @@ import { ILogService } from 'vs/platform/log/common/log';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IEditorProgressService } from 'vs/platform/progress/common/progress';
import { Registry } from 'vs/platform/registry/common/platform';
import { CONTEXT_RENAME_INPUT_FOCUSED, CONTEXT_RENAME_INPUT_VISIBLE, RenameInputField } from './renameInputField';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { CONTEXT_RENAME_INPUT_FOCUSED, CONTEXT_RENAME_INPUT_VISIBLE, RenameInputField, RenameInputFieldResult } from './renameInputField';
class RenameSkeleton {
@ -149,6 +150,7 @@ class RenameController implements IEditorContribution {
@ILogService private readonly _logService: ILogService,
@ITextResourceConfigurationService private readonly _configService: ITextResourceConfigurationService,
@ILanguageFeaturesService private readonly _languageFeaturesService: ILanguageFeaturesService,
@ITelemetryService private readonly _telemetryService: ITelemetryService,
) {
this._renameInputField = this._disposableStore.add(this._instaService.createInstance(RenameInputField, this.editor, ['acceptRenameInput', 'acceptRenameInputWithPreview']));
}
@ -240,6 +242,8 @@ class RenameController implements IEditorContribution {
const inputFieldResult = await this._renameInputField.getInput(loc.range, loc.text, selectionStart, selectionEnd, supportPreview, newSymbolNameProvidersResults, renameCandidatesCts);
trace('received response from rename input field');
this._reportTelemetry(inputFieldResult);
// no result, only hint to focus the editor or not
if (typeof inputFieldResult === 'boolean') {
trace(`returning early - rename input field response - ${inputFieldResult}`);
@ -325,6 +329,38 @@ class RenameController implements IEditorContribution {
focusPreviousRenameSuggestion(): void {
this._renameInputField.focusPreviousRenameSuggestion();
}
private _reportTelemetry(inputFieldResult: boolean | RenameInputFieldResult) {
type RenameInvokedEvent =
{
kind: 'accepted' | 'cancelled';
/** provided only if kind = 'accepted' */
wantsPreview?: boolean;
/** provided only if kind = 'accepted' */
source?: RenameInputFieldResult['source'];
/** provided only if kind = 'accepted' */
hadRenameSuggestions?: boolean;
};
type RenameInvokedClassification = {
owner: 'ulugbekna';
comment: 'A rename operation was invoked.';
kind: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether the rename operation was cancelled or accepted.' };
wantsPreview?: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'If user wanted preview.'; isMeasurement: true };
source?: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether the new name came from the input field or rename suggestions.' };
hadRenameSuggestions?: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether the user had rename suggestions.'; isMeasurement: true };
};
this._telemetryService.publicLog2<RenameInvokedEvent, RenameInvokedClassification>(
'renameInvokedEvent',
typeof inputFieldResult === 'boolean' ? { kind: 'cancelled' } : {
kind: 'accepted',
wantsPreview: inputFieldResult.wantsPreview,
source: inputFieldResult.source,
hadRenameSuggestions: inputFieldResult.hadRenameSuggestions,
}
);
}
}
// ---- action implementation

View file

@ -49,6 +49,8 @@ export const CONTEXT_RENAME_INPUT_FOCUSED = new RawContextKey<boolean>('renameIn
export interface RenameInputFieldResult {
newName: string;
wantsPreview?: boolean;
source: 'inputField' | 'renameSuggestion';
hadRenameSuggestions: boolean;
}
export class RenameInputField implements IContentWidget {
@ -298,7 +300,19 @@ export class RenameInputField implements IContentWidget {
assertType(this._input !== undefined);
assertType(this._candidatesView !== undefined);
const newName = this._candidatesView.focusedCandidate ?? this._input.value;
const hadRenameSuggestions = this._candidatesView.hasCandidates();
let newName: string;
let source: 'inputField' | 'renameSuggestion';
if (this._candidatesView.focusedCandidate !== undefined) {
this._trace('using new name from renameSuggestion');
newName = this._candidatesView.focusedCandidate;
source = 'renameSuggestion';
} else {
this._trace('using new name from inputField');
newName = this._input.value;
source = 'inputField';
}
if (newName === value || newName.trim().length === 0 /* is just whitespace */) {
this.cancelInput(true, '_currentAcceptInput (because newName === value || newName.trim().length === 0)');
@ -311,7 +325,9 @@ export class RenameInputField implements IContentWidget {
resolve({
newName,
wantsPreview: supportPreview && wantsPreview
wantsPreview: supportPreview && wantsPreview,
source,
hadRenameSuggestions,
});
};
@ -513,6 +529,10 @@ class CandidatesView {
this._listWidget.splice(0, this._listWidget.length, []);
}
public hasCandidates() {
return this._listWidget.length > 0;
}
public get focusedCandidate(): string | undefined {
if (this._listWidget.length === 0) {
return;