Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ export class GhostTextProvider {
opportunityId,
},
logContext,
telemetryBuilder.nesBuilder,
);

if (!rawCompletions) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ export class CopilotInlineCompletionItemProvider extends Disposable implements I

handleDidShowCompletionItem(item: GhostTextCompletionItem) {
try {
item.telemetryBuilder.setAsShown();
this.copilotCompletionFeedbackTracker.trackItem(item);
return this.ghostTextProvider.handleDidShowCompletionItem(item);
} catch (e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ITelemetryService } from '../../../../../../platform/telemetry/common/t
import { createSha256Hash } from '../../../../../../util/common/crypto';
import { generateUuid } from '../../../../../../util/vs/base/common/uuid';
import { IInstantiationService, ServicesAccessor } from '../../../../../../util/vs/platform/instantiation/common/instantiation';
import { LlmNESTelemetryBuilder } from '../../../../../inlineEdits/node/nextEditProviderTelemetry';
import { GhostTextLogContext } from '../../../../common/ghostTextContext';
import { initializeTokenizers } from '../../../prompt/src/tokenization';
import { CancellationTokenSource, CancellationToken as ICancellationToken } from '../../../types/src';
Expand Down Expand Up @@ -145,6 +146,7 @@ export class GhostTextComputer {
token: ICancellationToken | undefined,
options: Partial<GetGhostTextOptions>,
logContext: GhostTextLogContext,
telemetryBuilder: LlmNESTelemetryBuilder,
): Promise<GhostTextResultWithTelemetry<[CompletionResult[], ResultType]>> {
const id = generateUuid();
this.currentGhostText.currentRequestId = id;
Expand All @@ -164,7 +166,7 @@ export class GhostTextComputer {
options
);
this.notifierService.notifyRequest(completionState, id, telemetryData, token, options);
const result = await this.getGhostTextWithoutAbortHandling(completionState, id, telemetryData, token, options, logContext);
const result = await this.getGhostTextWithoutAbortHandling(completionState, id, telemetryData, token, options, logContext, telemetryBuilder);
const statistics = this.contextproviderStatistics.getStatisticsForCompletion(id);
const opportunityId = options?.opportunityId ?? 'unknown';
for (const [providerId, statistic] of statistics.getAllUsageStatistics()) {
Expand Down Expand Up @@ -219,6 +221,7 @@ export class GhostTextComputer {
cancellationToken: ICancellationToken | undefined,
options: Partial<GetGhostTextOptions>,
logContext: GhostTextLogContext,
telemetryBuilder: LlmNESTelemetryBuilder,
): Promise<GhostTextResultWithTelemetry<[CompletionResult[], ResultType]>> {
let start = preIssuedTelemetryDataWithExp.issuedTime; // Start before getting exp assignments
const performanceMetrics: [string, number][] = [];
Expand Down Expand Up @@ -436,6 +439,10 @@ export class GhostTextComputer {
.filter(c => c !== undefined);
}

if (choices && choices[1] === ResultType.Cache) {
telemetryBuilder.setIsFromCache();
}

if (choices !== undefined && choices[0].length === 0) {
this.logger.debug(`Found empty inline suggestions locally via ${resultTypeToString(choices[1])}`);
return {
Expand Down Expand Up @@ -632,10 +639,11 @@ export async function getGhostText(
token: ICancellationToken | undefined,
options: Partial<GetGhostTextOptions>,
logContext: GhostTextLogContext,
telemetryBuilder: LlmNESTelemetryBuilder,
): Promise<GhostTextResultWithTelemetry<[CompletionResult[], ResultType]>> {
const instaService = accessor.get(IInstantiationService);
const ghostTextComputer = instaService.createInstance(GhostTextComputer);
return ghostTextComputer.getGhostText(completionState, token, options, logContext);
return ghostTextComputer.getGhostText(completionState, token, options, logContext, telemetryBuilder);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { ICompletionsCurrentGhostText } from '../current';
import { getGhostText, GhostCompletion } from '../ghostText';
import { ResultType } from '../resultType';
import { mkBasicResultTelemetry } from '../telemetry';
import { LlmNESTelemetryBuilder } from '../../../../../../inlineEdits/node/nextEditProviderTelemetry';

// Unit tests for ghostText that do not require network connectivity. For other
// tests, see lib/e2e/src/ghostText.test.ts.
Expand Down Expand Up @@ -66,7 +67,8 @@ suite('Isolated GhostText tests', function () {

// Setup closures with the state as default
function requestGhostText(completionState = state) {
return getGhostText(accessor, completionState, token, {}, new GhostTextLogContext(filePath, doc.version, undefined));
const telemetryBuilder = new LlmNESTelemetryBuilder(undefined, undefined, undefined, 'ghostText', undefined);
return getGhostText(accessor, completionState, token, {}, new GhostTextLogContext(filePath, doc.version, undefined), telemetryBuilder);
}
async function requestPrompt(completionState = state) {
const telemExp = TelemetryWithExp.createEmptyConfigForTesting();
Expand Down Expand Up @@ -653,7 +655,8 @@ suite('Isolated GhostText tests', function () {
configProvider.setConfig(ConfigKey.AlwaysRequestMultiline, true);
currentGhostText.hasAcceptedCurrentCompletion = () => true;

const response = await getGhostText(accessor, state, undefined, { isSpeculative: true }, new GhostTextLogContext('file:///fizzbuzz.go', doc.version, undefined));
const telemetryBuilder = new LlmNESTelemetryBuilder(undefined, undefined, undefined, 'ghostText', undefined);
const response = await getGhostText(accessor, state, undefined, { isSpeculative: true }, new GhostTextLogContext('file:///fizzbuzz.go', doc.version, undefined), telemetryBuilder);

assert.strictEqual(response.type, 'success');
assert.strictEqual(response.value[0].length, 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { ICompletionsSpeculativeRequestCache } from './ghostText/speculativeRequ
import { GhostTextResultWithTelemetry, handleGhostTextResultTelemetry, logger } from './ghostText/telemetry';
import { ICompletionsLogTargetService } from './logger';
import { ITextDocument, TextDocumentContents } from './textDocument';
import { LlmNESTelemetryBuilder } from '../../../../inlineEdits/node/nextEditProviderTelemetry';

type GetInlineCompletionsOptions = Partial<GetGhostTextOptions> & {
formattingOptions?: ITextEditorOptions;
Expand All @@ -34,10 +35,11 @@ export class GhostText {
token: CancellationToken,
options: Exclude<Partial<GetInlineCompletionsOptions>, 'promptOnly'> = {},
logContext: GhostTextLogContext,
telemetryBuilder: LlmNESTelemetryBuilder,
): Promise<CopilotCompletion[] | undefined> {
logCompletionLocation(this.logTargetService, textDocument, position);

const result = await this.getInlineCompletionsResult(createCompletionState(textDocument, position), token, options, logContext);
const result = await this.getInlineCompletionsResult(createCompletionState(textDocument, position), token, options, logContext, telemetryBuilder);
return this.instantiationService.invokeFunction(handleGhostTextResultTelemetry, result);
}

Expand All @@ -46,6 +48,7 @@ export class GhostText {
token: CancellationToken,
options: GetInlineCompletionsOptions = {},
logContext: GhostTextLogContext,
telemetryBuilder: LlmNESTelemetryBuilder,
): Promise<GhostTextResultWithTelemetry<CopilotCompletion[]>> {
let lineLengthIncrease = 0;
// The golang.go extension (and quite possibly others) uses snippets for function completions, which collapse down
Expand All @@ -56,8 +59,12 @@ export class GhostText {
lineLengthIncrease = completionState.position.character - options.selectedCompletionInfo.range.end.character;
}

const result = await this.instantiationService.invokeFunction(getGhostText, completionState, token, options, logContext);
if (result.type !== 'success') { return result; }
const result = await this.instantiationService.invokeFunction(getGhostText, completionState, token, options, logContext, telemetryBuilder);

if (result.type !== 'success') {
return result;
}

const [resultArray, resultType] = result.value;

if (token.isCancellationRequested) {
Expand Down Expand Up @@ -95,7 +102,7 @@ export class GhostText {

// Cache speculative request to be triggered when telemetryShown is called
const specOpts = { isSpeculative: true, opportunityId: options.opportunityId };
const fn = () => this.instantiationService.invokeFunction(getGhostText, completionState, undefined, specOpts, logContext);
const fn = () => this.instantiationService.invokeFunction(getGhostText, completionState, undefined, specOpts, logContext, telemetryBuilder);
this.speculativeRequestCache.set(completions[0].clientCompletionId, fn);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { IPosition, ITextDocument } from '../../textDocument';
import { ICompletionsContextProviderBridgeService } from '../components/contextProviderBridge';
import { extractPrompt, ExtractPromptOptions } from '../prompt';
import { GhostTextLogContext } from '../../../../../common/ghostTextContext';
import { LlmNESTelemetryBuilder } from '../../../../../../inlineEdits/node/nextEditProviderTelemetry';

export async function extractPromptInternal(
accessor: ServicesAccessor,
Expand All @@ -33,5 +34,6 @@ export async function getGhostTextInternal(
position: IPosition,
token?: CancellationToken
) {
return getGhostText(accessor, createCompletionState(textDocument, position), token, { opportunityId: 'opId' }, new GhostTextLogContext(textDocument.uri, textDocument.version, undefined));
const telemetryBuilder = new LlmNESTelemetryBuilder(undefined, undefined, undefined, 'ghostText', undefined);
return getGhostText(accessor, createCompletionState(textDocument, position), token, { opportunityId: 'opId' }, new GhostTextLogContext(textDocument.uri, textDocument.version, undefined), telemetryBuilder);
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { createLibTestingContext } from './context';
import { createFakeCompletionResponse, StaticFetcher } from './fetcher';
import { withInMemoryTelemetry } from './telemetry';
import { createTextDocument } from './textDocument';
import { LlmNESTelemetryBuilder } from '../../../../../inlineEdits/node/nextEditProviderTelemetry';

suite('getInlineCompletions()', function () {
function setupCompletion(
Expand All @@ -38,7 +39,8 @@ suite('getInlineCompletions()', function () {
function requestInlineCompletions(textDoc = doc, pos = position) {
const instaService = accessor.get(IInstantiationService);
const ghostText = instaService.createInstance(GhostText);
return ghostText.getInlineCompletions(textDoc, pos, CancellationToken.None, undefined, new GhostTextLogContext(textDoc.uri, textDoc.version, undefined));
const telemetryBuilder = new LlmNESTelemetryBuilder(undefined, undefined, undefined, 'ghostText', undefined);
return ghostText.getInlineCompletions(textDoc, pos, CancellationToken.None, undefined, new GhostTextLogContext(textDoc.uri, textDoc.version, undefined), telemetryBuilder);
}

return {
Expand Down
3 changes: 2 additions & 1 deletion src/lib/node/chatLibMain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,8 @@ class InlineCompletionsProvider extends Disposable implements IInlineCompletions
}

async getInlineCompletions(textDocument: ITextDocument, position: Position, token?: CancellationToken, options?: IGetInlineCompletionsOptions): Promise<CopilotCompletion[] | undefined> {
return await this.ghostText.getInlineCompletions(textDocument, position, token ?? CancellationToken.None, options, new GhostTextLogContext(textDocument.uri, textDocument.version, undefined));
const telemetryBuilder = new LlmNESTelemetryBuilder(undefined, undefined, undefined, 'ghostText', undefined);
return await this.ghostText.getInlineCompletions(textDocument, position, token ?? CancellationToken.None, options, new GhostTextLogContext(textDocument.uri, textDocument.version, undefined), telemetryBuilder);
}

async inlineCompletionShown(completionId: string): Promise<void> {
Expand Down
Loading