From a86579d9a3ba5bcbc3d2bc661f2bdecbef94db1b Mon Sep 17 00:00:00 2001 From: Will Lo Date: Sat, 19 Jul 2025 21:24:57 -0700 Subject: [PATCH 1/6] config: disable inline tutorial since it's taking ~250ms for all users no matter it's shown or not --- packages/amazonq/src/app/inline/completion.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/amazonq/src/app/inline/completion.ts b/packages/amazonq/src/app/inline/completion.ts index 360be53e67a..23fa21dd380 100644 --- a/packages/amazonq/src/app/inline/completion.ts +++ b/packages/amazonq/src/app/inline/completion.ts @@ -319,9 +319,9 @@ export class AmazonQInlineCompletionItemProvider implements InlineCompletionItem this.sessionManager.clear() } - // TODO: this line will take ~200ms each trigger, need to root cause and maybe better to disable it for now + // TODO: this line will take ~200ms each trigger, need to root cause and re-enable once it's fixed // tell the tutorial that completions has been triggered - await this.inlineTutorialAnnotation.triggered(context.triggerKind) + // await this.inlineTutorialAnnotation.triggered(context.triggerKind) TelemetryHelper.instance.setInvokeSuggestionStartTime() TelemetryHelper.instance.setTriggerType(context.triggerKind) From 7fc40423a1fe9918c8d40bc8a8952b1234d3be48 Mon Sep 17 00:00:00 2001 From: Will Lo Date: Sat, 19 Jul 2025 22:02:20 -0700 Subject: [PATCH 2/6] linter --- packages/amazonq/src/app/inline/completion.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/amazonq/src/app/inline/completion.ts b/packages/amazonq/src/app/inline/completion.ts index 23fa21dd380..98d01069cfb 100644 --- a/packages/amazonq/src/app/inline/completion.ts +++ b/packages/amazonq/src/app/inline/completion.ts @@ -204,6 +204,7 @@ export class AmazonQInlineCompletionItemProvider implements InlineCompletionItem private readonly languageClient: LanguageClient, private readonly recommendationService: RecommendationService, private readonly sessionManager: SessionManager, + // eslint-disable-next-line no-unused-vars private readonly inlineTutorialAnnotation: InlineTutorialAnnotation, private readonly documentEventListener: DocumentEventListener ) {} From e6b57a677f222169fd93e00d2aeec43d6df3fcac Mon Sep 17 00:00:00 2001 From: Will Lo Date: Sat, 19 Jul 2025 22:31:46 -0700 Subject: [PATCH 3/6] add logs --- packages/amazonq/src/app/inline/completion.ts | 19 ++++--- .../src/app/inline/recommendationService.ts | 4 +- .../tutorials/inlineTutorialAnnotation.ts | 51 ++++++++----------- 3 files changed, 34 insertions(+), 40 deletions(-) diff --git a/packages/amazonq/src/app/inline/completion.ts b/packages/amazonq/src/app/inline/completion.ts index 98d01069cfb..8f3c81ec813 100644 --- a/packages/amazonq/src/app/inline/completion.ts +++ b/packages/amazonq/src/app/inline/completion.ts @@ -199,12 +199,11 @@ export class InlineCompletionManager implements Disposable { } export class AmazonQInlineCompletionItemProvider implements InlineCompletionItemProvider { - private logger = getLogger('nextEditPrediction') + private logger = getLogger() constructor( private readonly languageClient: LanguageClient, private readonly recommendationService: RecommendationService, private readonly sessionManager: SessionManager, - // eslint-disable-next-line no-unused-vars private readonly inlineTutorialAnnotation: InlineTutorialAnnotation, private readonly documentEventListener: DocumentEventListener ) {} @@ -320,9 +319,8 @@ export class AmazonQInlineCompletionItemProvider implements InlineCompletionItem this.sessionManager.clear() } - // TODO: this line will take ~200ms each trigger, need to root cause and re-enable once it's fixed // tell the tutorial that completions has been triggered - // await this.inlineTutorialAnnotation.triggered(context.triggerKind) + await this.inlineTutorialAnnotation.triggered(context.triggerKind) TelemetryHelper.instance.setInvokeSuggestionStartTime() TelemetryHelper.instance.setTriggerType(context.triggerKind) @@ -347,12 +345,13 @@ export class AmazonQInlineCompletionItemProvider implements InlineCompletionItem const t2 = performance.now() - logstr = logstr += `- number of suggestions: ${items.length} + logstr += `- number of suggestions: ${items.length} - sessionId: ${this.sessionManager.getActiveSession()?.sessionId} - first suggestion content (next line): ${itemLog} -- duration since trigger to before sending Flare call: ${t1 - t0}ms -- duration since trigger to receiving responses from Flare: ${t2 - t0}ms +- duration between trigger to before sending LSP call: ${t1 - t0}ms +- duration between trigger to after receiving LSP response: ${t2 - t0}ms +- duration between before sending LSP call to after receving LSP response: ${t2 - t1}ms ` const session = this.sessionManager.getActiveSession() @@ -411,9 +410,7 @@ ${itemLog} // Check if Next Edit Prediction feature flag is enabled if (Experiments.instance.get('amazonqLSPNEP', true)) { await showEdits(item, editor, session, this.languageClient, this) - const t3 = performance.now() - logstr = logstr + `- duration since trigger to NEP suggestion is displayed: ${t3 - t0}ms` - this.logger.info(logstr) + logstr += `- duration between trigger to edits suggestion is displayed: ${performance.now() - t0}ms` } return [] } @@ -459,12 +456,14 @@ ${itemLog} } // suggestions returned here will be displayed on screen + logstr += `- duration between trigger to completion suggestion is displayed: ${performance.now() - t0}ms` return itemsMatchingTypeahead as InlineCompletionItem[] } catch (e) { getLogger('amazonqLsp').error('Failed to provide completion items: %O', e) return [] } finally { vsCodeState.isRecommendationsActive = false + this.logger.info(logstr) } } } diff --git a/packages/amazonq/src/app/inline/recommendationService.ts b/packages/amazonq/src/app/inline/recommendationService.ts index ddde310999f..7ec384d72c9 100644 --- a/packages/amazonq/src/app/inline/recommendationService.ts +++ b/packages/amazonq/src/app/inline/recommendationService.ts @@ -79,13 +79,15 @@ export class RecommendationService { nextToken: request.partialResultToken, }, }) + const t0 = performance.now() const result: InlineCompletionListWithReferences = await languageClient.sendRequest( inlineCompletionWithReferencesRequestType.method, request, token ) - getLogger().info('Received inline completion response: %O', { + getLogger().info('Received inline completion response from LSP: %O', { sessionId: result.sessionId, + latency: performance.now() - t0, itemCount: result.items?.length || 0, items: result.items?.map((item) => ({ itemId: item.itemId, diff --git a/packages/amazonq/src/app/inline/tutorials/inlineTutorialAnnotation.ts b/packages/amazonq/src/app/inline/tutorials/inlineTutorialAnnotation.ts index bd12b1d28dd..ad0807df94c 100644 --- a/packages/amazonq/src/app/inline/tutorials/inlineTutorialAnnotation.ts +++ b/packages/amazonq/src/app/inline/tutorials/inlineTutorialAnnotation.ts @@ -5,13 +5,7 @@ import * as vscode from 'vscode' import * as os from 'os' -import { - AnnotationChangeSource, - AuthUtil, - inlinehintKey, - runtimeLanguageContext, - TelemetryHelper, -} from 'aws-core-vscode/codewhisperer' +import { AnnotationChangeSource, AuthUtil, inlinehintKey, runtimeLanguageContext } from 'aws-core-vscode/codewhisperer' import { editorUtilities, getLogger, globals, setContext, vscodeUtilities } from 'aws-core-vscode/shared' import { LinesChangeEvent, LineSelection, LineTracker } from '../stateTracker/lineTracker' import { telemetry } from 'aws-core-vscode/telemetry' @@ -296,28 +290,27 @@ export class InlineTutorialAnnotation implements vscode.Disposable { } async triggered(triggerType: vscode.InlineCompletionTriggerKind): Promise { - await telemetry.withTraceId(async () => { - if (!this._isReady) { - return - } - - if (this._currentState instanceof ManualtriggerState) { - if ( - triggerType === vscode.InlineCompletionTriggerKind.Invoke && - this._currentState.hasManualTrigger === false - ) { - this._currentState.hasManualTrigger = true - } - if ( - this.sessionManager.getActiveRecommendation().length > 0 && - this._currentState.hasValidResponse === false - ) { - this._currentState.hasValidResponse = true - } - } - - await this.refresh(vscode.window.activeTextEditor, 'codewhisperer') - }, TelemetryHelper.instance.traceId) + // TODO: this logic will take ~200ms each trigger, need to root cause and re-enable once it's fixed, or it should only be invoked when the tutorial is actually needed + // await telemetry.withTraceId(async () => { + // if (!this._isReady) { + // return + // } + // if (this._currentState instanceof ManualtriggerState) { + // if ( + // triggerType === vscode.InlineCompletionTriggerKind.Invoke && + // this._currentState.hasManualTrigger === false + // ) { + // this._currentState.hasManualTrigger = true + // } + // if ( + // this.sessionManager.getActiveRecommendation().length > 0 && + // this._currentState.hasValidResponse === false + // ) { + // this._currentState.hasValidResponse = true + // } + // } + // await this.refresh(vscode.window.activeTextEditor, 'codewhisperer') + // }, TelemetryHelper.instance.traceId) } isTutorialDone(): boolean { From f1ae5bf797ce1ecb862f4885949f548de0d2ea13 Mon Sep 17 00:00:00 2001 From: Will Lo Date: Sat, 19 Jul 2025 22:34:42 -0700 Subject: [PATCH 4/6] todo --- packages/amazonq/src/app/inline/recommendationService.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/amazonq/src/app/inline/recommendationService.ts b/packages/amazonq/src/app/inline/recommendationService.ts index 7ec384d72c9..c00ee797d13 100644 --- a/packages/amazonq/src/app/inline/recommendationService.ts +++ b/packages/amazonq/src/app/inline/recommendationService.ts @@ -117,6 +117,7 @@ export class RecommendationService { const isInlineEdit = result.items.some((item) => item.isInlineEdit) + // TODO: question, is it possible that the first request returns empty suggestion but has non-empty next token? if (result.partialResultToken) { if (!isInlineEdit) { // If the suggestion is COMPLETIONS and there are more results to fetch, handle them in the background From f322796afb0b4cf0a5b59e4a5575449da01b56ab Mon Sep 17 00:00:00 2001 From: Will Lo Date: Sat, 19 Jul 2025 22:45:48 -0700 Subject: [PATCH 5/6] imporve log --- packages/amazonq/src/app/inline/completion.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/amazonq/src/app/inline/completion.ts b/packages/amazonq/src/app/inline/completion.ts index 8f3c81ec813..ecf95b46963 100644 --- a/packages/amazonq/src/app/inline/completion.ts +++ b/packages/amazonq/src/app/inline/completion.ts @@ -300,7 +300,8 @@ export class AmazonQInlineCompletionItemProvider implements InlineCompletionItem } // re-use previous suggestions as long as new typed prefix matches if (prevItemMatchingPrefix.length > 0) { - getLogger().debug(`Re-using suggestions that match user typed characters`) + logstr += `- not calling LSP and reuse previous suggestions that match user typed characters + - duration between trigger to completion suggestion is displayed ${performance.now() - t0}` return prevItemMatchingPrefix } getLogger().debug(`Auto rejecting suggestions from previous session`) @@ -361,16 +362,13 @@ ${itemLog} } if (!session || !items.length || !editor) { - getLogger().debug( - `Failed to produce inline suggestion results. Received ${items.length} items from service` - ) + logstr += `Failed to produce inline suggestion results. Received ${items.length} items from service` return [] } const cursorPosition = document.validatePosition(position) if (position.isAfter(editor.selection.active)) { - getLogger().debug(`Cursor moved behind trigger position. Discarding suggestion...`) const params: LogInlineCompletionSessionResultsParams = { sessionId: session.sessionId, completionSessionResult: { @@ -383,6 +381,7 @@ ${itemLog} } this.languageClient.sendNotification(this.logSessionResultMessageName, params) this.sessionManager.clear() + logstr += `- cursor moved behind trigger position. Discarding suggestion...` return [] } @@ -437,9 +436,6 @@ ${itemLog} // report discard if none of suggestions match typeahead if (itemsMatchingTypeahead.length === 0) { - getLogger().debug( - `Suggestion does not match user typeahead from insertion position. Discarding suggestion...` - ) const params: LogInlineCompletionSessionResultsParams = { sessionId: session.sessionId, completionSessionResult: { @@ -452,6 +448,7 @@ ${itemLog} } this.languageClient.sendNotification(this.logSessionResultMessageName, params) this.sessionManager.clear() + logstr += `- suggestion does not match user typeahead from insertion position. Discarding suggestion...` return [] } @@ -460,6 +457,7 @@ ${itemLog} return itemsMatchingTypeahead as InlineCompletionItem[] } catch (e) { getLogger('amazonqLsp').error('Failed to provide completion items: %O', e) + logstr += `- failed to provide completion items ${(e as Error).message}` return [] } finally { vsCodeState.isRecommendationsActive = false From e4feefbdf131d45a8bc0410519b066b2200f3b20 Mon Sep 17 00:00:00 2001 From: Will Lo Date: Sat, 19 Jul 2025 22:46:35 -0700 Subject: [PATCH 6/6] typo --- packages/amazonq/src/app/inline/completion.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/amazonq/src/app/inline/completion.ts b/packages/amazonq/src/app/inline/completion.ts index ecf95b46963..2bb64041b47 100644 --- a/packages/amazonq/src/app/inline/completion.ts +++ b/packages/amazonq/src/app/inline/completion.ts @@ -300,7 +300,7 @@ export class AmazonQInlineCompletionItemProvider implements InlineCompletionItem } // re-use previous suggestions as long as new typed prefix matches if (prevItemMatchingPrefix.length > 0) { - logstr += `- not calling LSP and reuse previous suggestions that match user typed characters + logstr += `- not call LSP and reuse previous suggestions that match user typed characters - duration between trigger to completion suggestion is displayed ${performance.now() - t0}` return prevItemMatchingPrefix }