Skip to content

Commit e2470cf

Browse files
authored
tweak resolve info so that we know if resolve was needed and if it already finished, also make telemetry gate more fair (microsoft#185327)
* tweak resolve info so that we know if resolve was needed and if it already finished, also make telemetry gate more fair * also log the resolve duration
1 parent dedbfed commit e2470cf

File tree

2 files changed

+26
-17
lines changed

2 files changed

+26
-17
lines changed

src/vs/editor/contrib/suggest/browser/suggest.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export class CompletionItem {
7373
readonly extensionId?: ExtensionIdentifier;
7474

7575
// resolving
76-
private _isResolved?: boolean;
76+
private _resolveDuration?: number;
7777
private _resolveCache?: Promise<void>;
7878

7979
constructor(
@@ -122,32 +122,37 @@ export class CompletionItem {
122122
// create the suggestion resolver
123123
if (typeof provider.resolveCompletionItem !== 'function') {
124124
this._resolveCache = Promise.resolve();
125-
this._isResolved = true;
125+
this._resolveDuration = 0;
126126
}
127127
}
128128

129129
// ---- resolving
130130

131131
get isResolved(): boolean {
132-
return !!this._isResolved;
132+
return this._resolveDuration !== undefined;
133+
}
134+
135+
get resolveDuration(): number {
136+
return this._resolveDuration !== undefined ? this._resolveDuration : -1;
133137
}
134138

135139
async resolve(token: CancellationToken) {
136140
if (!this._resolveCache) {
137141
const sub = token.onCancellationRequested(() => {
138142
this._resolveCache = undefined;
139-
this._isResolved = false;
143+
this._resolveDuration = undefined;
140144
});
145+
const sw = new StopWatch(true);
141146
this._resolveCache = Promise.resolve(this.provider.resolveCompletionItem!(this.completion, token)).then(value => {
142147
Object.assign(this.completion, value);
143-
this._isResolved = true;
148+
this._resolveDuration = sw.elapsed();
144149
sub.dispose();
145150
}, err => {
146151
if (isCancellationError(err)) {
147152
// the IPC queue will reject the request with the
148153
// cancellation error -> reset cached
149154
this._resolveCache = undefined;
150-
this._isResolved = false;
155+
this._resolveDuration = undefined;
151156
}
152157
});
153158
}

src/vs/editor/contrib/suggest/browser/suggestController.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -482,20 +482,24 @@ export class SuggestController implements IEditorContribution {
482482

483483
// clear only now - after all tasks are done
484484
Promise.all(tasks).finally(() => {
485-
this._reportSuggestionAcceptedTelemetry(item, model, event, isResolved);
485+
this._reportSuggestionAcceptedTelemetry(item, model, isResolved);
486486

487487
this.model.clear();
488488
cts.dispose();
489489
});
490490
}
491491

492-
private _telemetryGate: number = 0;
493-
private _reportSuggestionAcceptedTelemetry(item: CompletionItem, model: ITextModel, acceptedSuggestion: ISelectedSuggestion, itemResolved: boolean) {
494-
if (this._telemetryGate++ % 100 !== 0) {
492+
private _reportSuggestionAcceptedTelemetry(item: CompletionItem, model: ITextModel, itemResolved: boolean) {
493+
494+
if (Math.floor(Math.random() * 100) === 0) {
495+
// throttle telemetry event because accepting completions happens a lot
495496
return;
496497
}
497498

498-
type AcceptedSuggestion = { providerId: string; fileExtension: string; languageId: string; basenameHash: string; kind: number; itemResolved: boolean };
499+
type AcceptedSuggestion = {
500+
providerId: string; fileExtension: string; languageId: string; basenameHash: string; kind: number;
501+
resolveInfo: number; resolveDuration: number;
502+
};
499503
type AcceptedSuggestionClassification = {
500504
owner: 'jrieken';
501505
comment: 'Information accepting completion items';
@@ -504,18 +508,18 @@ export class SuggestController implements IEditorContribution {
504508
fileExtension: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'File extension of the file into which the completion was inserted' };
505509
languageId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Language type of the file into which the completion was inserted' };
506510
kind: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; comment: 'The completion item kind' };
507-
itemResolved: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; comment: 'If the item was inserted before resolving was done' };
511+
resolveInfo: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; comment: 'If the item was inserted before resolving was done' };
512+
resolveDuration: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; comment: 'How long resolving took to finish' };
508513
};
509-
// _debugDisplayName looks like `vscode.css-language-features(/-:)`, where the last bit is the trigger chars
510-
// normalize it to just the extension ID and lowercase
511-
const providerId = item.extensionId ? item.extensionId.value : (acceptedSuggestion.item.provider._debugDisplayName ?? 'unknown').split('(', 1)[0].toLowerCase();
514+
512515
this._telemetryService.publicLog2<AcceptedSuggestion, AcceptedSuggestionClassification>('suggest.acceptedSuggestion', {
513-
providerId,
516+
providerId: item.extensionId?.value ?? 'unknown',
514517
kind: item.completion.kind,
515518
basenameHash: hash(basename(model.uri)).toString(16),
516519
languageId: model.getLanguageId(),
517520
fileExtension: extname(model.uri),
518-
itemResolved
521+
resolveInfo: !item.provider.resolveCompletionItem ? -1 : itemResolved ? 1 : 0,
522+
resolveDuration: item.resolveDuration
519523
});
520524
}
521525

0 commit comments

Comments
 (0)