Skip to content

Commit ade8208

Browse files
committed
fix(amazonq): batch telemetry for edits
1 parent ac4c778 commit ade8208

File tree

2 files changed

+152
-18
lines changed

2 files changed

+152
-18
lines changed

packages/amazonq/src/app/inline/completion.ts

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,37 @@ export class AmazonQInlineCompletionItemProvider implements InlineCompletionItem
245245
return session !== undefined && session.displayed && !session.suggestions.some((item) => item.isInlineEdit)
246246
}
247247

248+
/**
249+
* Batch discard telemetry for completion suggestions when edit suggestion is active
250+
*/
251+
public batchDiscardTelemetryForEditSuggestion(items: any[], session: any): void {
252+
// Emit DISCARD telemetry for completion suggestions that can't be shown due to active edit
253+
const completionSessionResult: {
254+
[key: string]: { seen: boolean; accepted: boolean; discarded: boolean }
255+
} = {}
256+
257+
for (const item of items) {
258+
if (!item.isInlineEdit && item.itemId) {
259+
completionSessionResult[item.itemId] = {
260+
seen: false,
261+
accepted: false,
262+
discarded: true,
263+
}
264+
}
265+
}
266+
267+
// Send single telemetry event for all discarded items
268+
if (Object.keys(completionSessionResult).length > 0) {
269+
const params: LogInlineCompletionSessionResultsParams = {
270+
sessionId: session.sessionId,
271+
completionSessionResult,
272+
firstCompletionDisplayLatency: session.firstCompletionDisplayLatency,
273+
totalSessionDisplayTime: performance.now() - session.requestStartTime,
274+
}
275+
this.languageClient.sendNotification(this.logSessionResultMessageName, params)
276+
}
277+
}
278+
248279
/**
249280
* Check if an edit suggestion is currently active
250281
*/
@@ -452,24 +483,7 @@ ${itemLog}
452483

453484
// Check if an edit suggestion is currently active - if so, discard completion suggestions
454485
if (this.isEditSuggestionActive()) {
455-
// Emit DISCARD telemetry for completion suggestions that can't be shown due to active edit
456-
for (const item of items) {
457-
if (!item.isInlineEdit && item.itemId) {
458-
const params: LogInlineCompletionSessionResultsParams = {
459-
sessionId: session.sessionId,
460-
completionSessionResult: {
461-
[item.itemId]: {
462-
seen: false,
463-
accepted: false,
464-
discarded: true,
465-
},
466-
},
467-
firstCompletionDisplayLatency: session.firstCompletionDisplayLatency,
468-
totalSessionDisplayTime: performance.now() - session.requestStartTime,
469-
}
470-
this.languageClient.sendNotification(this.logSessionResultMessageName, params)
471-
}
472-
}
486+
this.batchDiscardTelemetryForEditSuggestion(items, session)
473487
this.sessionManager.clear()
474488
logstr += `- completion suggestions discarded due to active edit suggestion`
475489
return []
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import * as assert from 'assert'
7+
import * as sinon from 'sinon'
8+
import { AmazonQInlineCompletionItemProvider } from '../../../../src/app/inline/completion'
9+
10+
describe('AmazonQInlineCompletionItemProvider', function () {
11+
let provider: AmazonQInlineCompletionItemProvider
12+
let mockLanguageClient: any
13+
let sandbox: sinon.SinonSandbox
14+
15+
beforeEach(function () {
16+
sandbox = sinon.createSandbox()
17+
mockLanguageClient = {
18+
sendNotification: sandbox.stub(),
19+
}
20+
21+
// Create provider with minimal mocks
22+
provider = new AmazonQInlineCompletionItemProvider(
23+
mockLanguageClient,
24+
{} as any, // recommendationService
25+
{} as any, // sessionManager
26+
{} as any, // inlineTutorialAnnotation
27+
{} as any // documentEventListener
28+
)
29+
})
30+
31+
afterEach(function () {
32+
sandbox.restore()
33+
})
34+
35+
describe('batchDiscardTelemetryForEditSuggestion', function () {
36+
it('should batch multiple completion items into single telemetry event', function () {
37+
const items = [
38+
{ itemId: 'item1', isInlineEdit: false },
39+
{ itemId: 'item2', isInlineEdit: false },
40+
{ itemId: 'item3', isInlineEdit: false },
41+
]
42+
43+
const session = {
44+
sessionId: 'test-session',
45+
firstCompletionDisplayLatency: 100,
46+
requestStartTime: performance.now() - 1000,
47+
}
48+
49+
provider.batchDiscardTelemetryForEditSuggestion(items, session)
50+
51+
// Verify single telemetry notification was sent
52+
assert.strictEqual(mockLanguageClient.sendNotification.callCount, 1)
53+
54+
// Verify the notification contains all items
55+
const call = mockLanguageClient.sendNotification.getCall(0)
56+
const params = call.args[1]
57+
58+
assert.strictEqual(params.sessionId, 'test-session')
59+
assert.strictEqual(Object.keys(params.completionSessionResult).length, 3)
60+
assert.deepStrictEqual(params.completionSessionResult.item1, {
61+
seen: false,
62+
accepted: false,
63+
discarded: true,
64+
})
65+
assert.deepStrictEqual(params.completionSessionResult.item2, {
66+
seen: false,
67+
accepted: false,
68+
discarded: true,
69+
})
70+
assert.deepStrictEqual(params.completionSessionResult.item3, {
71+
seen: false,
72+
accepted: false,
73+
discarded: true,
74+
})
75+
})
76+
77+
it('should filter out inline edit items', function () {
78+
const items = [
79+
{ itemId: 'item1', isInlineEdit: false },
80+
{ itemId: 'item2', isInlineEdit: true }, // Should be filtered out
81+
{ itemId: 'item3', isInlineEdit: false },
82+
]
83+
84+
const session = {
85+
sessionId: 'test-session',
86+
firstCompletionDisplayLatency: 100,
87+
requestStartTime: performance.now() - 1000,
88+
}
89+
90+
provider.batchDiscardTelemetryForEditSuggestion(items, session)
91+
92+
const call = mockLanguageClient.sendNotification.getCall(0)
93+
const params = call.args[1]
94+
95+
// Should only include 2 items (item2 filtered out)
96+
assert.strictEqual(Object.keys(params.completionSessionResult).length, 2)
97+
assert.ok(params.completionSessionResult.item1)
98+
assert.ok(params.completionSessionResult.item3)
99+
assert.ok(!params.completionSessionResult.item2)
100+
})
101+
102+
it('should not send notification when no valid items', function () {
103+
const items = [
104+
{ itemId: 'item1', isInlineEdit: true }, // Filtered out
105+
{ itemId: null, isInlineEdit: false }, // No itemId
106+
]
107+
108+
const session = {
109+
sessionId: 'test-session',
110+
firstCompletionDisplayLatency: 100,
111+
requestStartTime: performance.now() - 1000,
112+
}
113+
114+
provider.batchDiscardTelemetryForEditSuggestion(items, session)
115+
116+
// No notification should be sent
117+
assert.strictEqual(mockLanguageClient.sendNotification.callCount, 0)
118+
})
119+
})
120+
})

0 commit comments

Comments
 (0)