Skip to content

Commit 2f5bd78

Browse files
committed
merge in upstream changes
2 parents 2ca5e32 + d6336e4 commit 2f5bd78

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+198
-132
lines changed

docs/arch_features.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ For connecting a new VSCode _terminal_, remote connect works like this:
3939
1. Toolkit [builds a session-manager-plugin command](https://github.com/aws/aws-toolkit-vscode/blob/c77fc076fd0ed837d077bc0318716b711a2854c8/packages/core/src/ecs/util.ts#L92-L104) and [passes it to a new VSCode Terminal](https://github.com/aws/aws-toolkit-vscode/blob/c77fc076fd0ed837d077bc0318716b711a2854c8/packages/core/src/ecs/commands.ts#L141-L147).
4040
1. VSCode displays the terminal, so the user can enter shell commands on the remote machine.
4141

42+
For EC2 specifically, there are a few additional steps:
43+
44+
1. If connecting to EC2 instance via remote window, the toolkit generates temporary SSH keys (30 second lifetime), with the public key sent to the remote instance.
45+
- Key type is ed25519 if supported, or RSA otherwise.
46+
1. If insufficient permissions are detected on the attached IAM role, toolkit will prompt to add an inline policy with the necessary actions.
47+
1. If SSM sessions remain open after closing the window/terminal, the toolkit will terminate them on-shutdown, or when starting another session to the same instance.
48+
4249
### Implementation of remote connect
4350

4451
These modules show how to use and extend the "remote connect" functionality:

packages/core/src/awsService/ecs/commands.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const localize = nls.loadMessageBundle()
99
import * as vscode from 'vscode'
1010
import globals from '../../shared/extensionGlobals'
1111
import { ToolkitPromptSettings } from '../../shared/settings'
12-
import { ChildProcess } from '../../shared/utilities/childProcess'
12+
import { ChildProcess } from '../../shared/utilities/processUtils'
1313
import { showMessageWithCancel, showOutputMessage } from '../../shared/utilities/messages'
1414
import { formatDateTimestamp, removeAnsi } from '../../shared/utilities/textUtilities'
1515
import { CancellationError, Timeout } from '../../shared/utilities/timeoutUtils'

packages/core/src/codecatalyst/model.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { AsyncCollection, toCollection } from '../shared/utilities/asyncCollecti
2020
import { getCodeCatalystSpaceName, getCodeCatalystProjectName, getCodeCatalystDevEnvId } from '../shared/vscode/env'
2121
import { writeFile } from 'fs-extra'
2222
import { sshAgentSocketVariable, startSshAgent, startVscodeRemote } from '../shared/extensions/ssh'
23-
import { ChildProcess } from '../shared/utilities/childProcess'
23+
import { ChildProcess } from '../shared/utilities/processUtils'
2424
import { isDevenvVscode } from './utils'
2525
import { Timeout } from '../shared/utilities/timeoutUtils'
2626
import { Commands } from '../shared/vscode/commands2'

packages/core/src/codewhisperer/activation.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,11 @@ export async function activate(context: ExtContext): Promise<void> {
200200
await openSettings('amazonQ')
201201
}
202202
}),
203-
Commands.register('aws.amazonq.refreshAnnotation', async (forceProceed: boolean = false) => {
203+
Commands.register('aws.amazonq.refreshAnnotation', async (forceProceed: boolean) => {
204+
telemetry.record({
205+
traceId: TelemetryHelper.instance.traceId,
206+
})
207+
204208
const editor = vscode.window.activeTextEditor
205209
if (editor) {
206210
if (forceProceed) {

packages/core/src/codewhisperer/commands/onInlineAcceptance.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import { session } from '../util/codeWhispererSession'
3030
import path from 'path'
3131
import { RecommendationService } from '../service/recommendationService'
3232
import { Container } from '../service/serviceContainer'
33+
import { telemetry } from '../../shared/telemetry'
34+
import { TelemetryHelper } from '../util/telemetryHelper'
3335

3436
export const acceptSuggestion = Commands.declare(
3537
'aws.amazonq.accept',
@@ -46,6 +48,10 @@ export const acceptSuggestion = Commands.declare(
4648
language: CodewhispererLanguage,
4749
references: codewhispererClient.References
4850
) => {
51+
telemetry.record({
52+
traceId: TelemetryHelper.instance.traceId,
53+
})
54+
4955
RecommendationService.instance.incrementAcceptedCount()
5056
const editor = vscode.window.activeTextEditor
5157
await Container.instance.lineAnnotationController.refresh(editor, 'codewhisperer')

packages/core/src/codewhisperer/service/keyStrokeHandler.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ export class KeyStrokeHandler {
164164
if (!editor) {
165165
return
166166
}
167+
167168
// RecommendationHandler.instance.reportUserDecisionOfRecommendation(editor, -1)
168169
await RecommendationService.instance.generateRecommendation(
169170
client,

packages/core/src/codewhisperer/service/recommendationHandler.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ const nextCommand = Commands.declare('editor.action.inlineSuggest.showNext', ()
5959
})
6060

6161
const rejectCommand = Commands.declare('aws.amazonq.rejectCodeSuggestion', () => async () => {
62+
telemetry.record({
63+
traceId: TelemetryHelper.instance.traceId,
64+
})
65+
6266
if (!isCloud9('any')) {
6367
await vscode.commands.executeCommand('editor.action.inlineSuggest.hide')
6468
}

packages/core/src/codewhisperer/service/recommendationService.ts

Lines changed: 96 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,19 @@ import * as vscode from 'vscode'
66
import { ConfigurationEntry, GetRecommendationsResponse, vsCodeState } from '../models/model'
77
import { isCloud9 } from '../../shared/extensionUtilities'
88
import { isInlineCompletionEnabled } from '../util/commonUtil'
9-
import { CodewhispererAutomatedTriggerType, CodewhispererTriggerType } from '../../shared/telemetry/telemetry'
9+
import {
10+
CodewhispererAutomatedTriggerType,
11+
CodewhispererTriggerType,
12+
telemetry,
13+
} from '../../shared/telemetry/telemetry'
1014
import { AuthUtil } from '../util/authUtil'
1115
import { isIamConnection } from '../../auth/connection'
1216
import { RecommendationHandler } from '../service/recommendationHandler'
1317
import { InlineCompletionService } from '../service/inlineCompletionService'
1418
import { ClassifierTrigger } from './classifierTrigger'
1519
import { DefaultCodeWhispererClient } from '../client/codewhisperer'
20+
import { randomUUID } from '../../shared/crypto'
21+
import { TelemetryHelper } from '../util/telemetryHelper'
1622

1723
export interface SuggestionActionEvent {
1824
readonly editor: vscode.TextEditor | undefined
@@ -68,99 +74,107 @@ export class RecommendationService {
6874
return
6975
}
7076

71-
if (isCloud9('any')) {
72-
// C9 manual trigger key alt/option + C is ALWAYS enabled because the VSC version C9 is on doesn't support setContextKey which is used for CODEWHISPERER_ENABLED
73-
// therefore we need a connection check if there is ANY connection(regardless of the connection's state) connected to CodeWhisperer on C9
74-
if (triggerType === 'OnDemand' && !AuthUtil.instance.isConnected()) {
75-
return
76-
}
77+
/**
78+
* Use an existing trace ID if invoked through a command (e.g., manual invocation),
79+
* otherwise generate a new trace ID
80+
*/
81+
const traceId = telemetry.attributes?.traceId ?? randomUUID()
82+
TelemetryHelper.instance.setTraceId(traceId)
83+
await telemetry.withTraceId(async () => {
84+
if (isCloud9('any')) {
85+
// C9 manual trigger key alt/option + C is ALWAYS enabled because the VSC version C9 is on doesn't support setContextKey which is used for CODEWHISPERER_ENABLED
86+
// therefore we need a connection check if there is ANY connection(regardless of the connection's state) connected to CodeWhisperer on C9
87+
if (triggerType === 'OnDemand' && !AuthUtil.instance.isConnected()) {
88+
return
89+
}
7790

78-
RecommendationHandler.instance.checkAndResetCancellationTokens()
79-
vsCodeState.isIntelliSenseActive = false
80-
this._isRunning = true
81-
let response: GetRecommendationsResponse = {
82-
result: 'Failed',
83-
errorMessage: undefined,
84-
recommendationCount: 0,
85-
}
91+
RecommendationHandler.instance.checkAndResetCancellationTokens()
92+
vsCodeState.isIntelliSenseActive = false
93+
this._isRunning = true
94+
let response: GetRecommendationsResponse = {
95+
result: 'Failed',
96+
errorMessage: undefined,
97+
recommendationCount: 0,
98+
}
8699

87-
try {
88-
this._onSuggestionActionEvent.fire({
89-
editor: editor,
90-
isRunning: true,
91-
triggerType: triggerType,
92-
response: undefined,
93-
})
100+
try {
101+
this._onSuggestionActionEvent.fire({
102+
editor: editor,
103+
isRunning: true,
104+
triggerType: triggerType,
105+
response: undefined,
106+
})
94107

95-
if (isCloud9('classic') || isIamConnection(AuthUtil.instance.conn)) {
96-
response = await RecommendationHandler.instance.getRecommendations(
97-
client,
98-
editor,
99-
triggerType,
100-
config,
101-
autoTriggerType,
102-
false
103-
)
104-
} else {
105-
if (AuthUtil.instance.isConnectionExpired()) {
106-
await AuthUtil.instance.showReauthenticatePrompt()
108+
if (isCloud9('classic') || isIamConnection(AuthUtil.instance.conn)) {
109+
response = await RecommendationHandler.instance.getRecommendations(
110+
client,
111+
editor,
112+
triggerType,
113+
config,
114+
autoTriggerType,
115+
false
116+
)
117+
} else {
118+
if (AuthUtil.instance.isConnectionExpired()) {
119+
await AuthUtil.instance.showReauthenticatePrompt()
120+
}
121+
response = await RecommendationHandler.instance.getRecommendations(
122+
client,
123+
editor,
124+
triggerType,
125+
config,
126+
autoTriggerType,
127+
true
128+
)
129+
}
130+
if (RecommendationHandler.instance.canShowRecommendationInIntelliSense(editor, true, response)) {
131+
await vscode.commands.executeCommand('editor.action.triggerSuggest').then(() => {
132+
vsCodeState.isIntelliSenseActive = true
133+
})
107134
}
108-
response = await RecommendationHandler.instance.getRecommendations(
135+
} finally {
136+
this._isRunning = false
137+
this._onSuggestionActionEvent.fire({
138+
editor: editor,
139+
isRunning: false,
140+
triggerType: triggerType,
141+
response: response,
142+
})
143+
}
144+
} else if (isInlineCompletionEnabled()) {
145+
if (triggerType === 'OnDemand') {
146+
ClassifierTrigger.instance.recordClassifierResultForManualTrigger(editor)
147+
}
148+
149+
this._isRunning = true
150+
let response: GetRecommendationsResponse | undefined = undefined
151+
152+
try {
153+
this._onSuggestionActionEvent.fire({
154+
editor: editor,
155+
isRunning: true,
156+
triggerType: triggerType,
157+
response: undefined,
158+
})
159+
160+
response = await InlineCompletionService.instance.getPaginatedRecommendation(
109161
client,
110162
editor,
111163
triggerType,
112164
config,
113165
autoTriggerType,
114-
true
166+
event
115167
)
116-
}
117-
if (RecommendationHandler.instance.canShowRecommendationInIntelliSense(editor, true, response)) {
118-
await vscode.commands.executeCommand('editor.action.triggerSuggest').then(() => {
119-
vsCodeState.isIntelliSenseActive = true
168+
} finally {
169+
this._isRunning = false
170+
this._onSuggestionActionEvent.fire({
171+
editor: editor,
172+
isRunning: false,
173+
triggerType: triggerType,
174+
response: response,
120175
})
121176
}
122-
} finally {
123-
this._isRunning = false
124-
this._onSuggestionActionEvent.fire({
125-
editor: editor,
126-
isRunning: false,
127-
triggerType: triggerType,
128-
response: response,
129-
})
130-
}
131-
} else if (isInlineCompletionEnabled()) {
132-
if (triggerType === 'OnDemand') {
133-
ClassifierTrigger.instance.recordClassifierResultForManualTrigger(editor)
134177
}
135-
136-
this._isRunning = true
137-
let response: GetRecommendationsResponse | undefined = undefined
138-
139-
try {
140-
this._onSuggestionActionEvent.fire({
141-
editor: editor,
142-
isRunning: true,
143-
triggerType: triggerType,
144-
response: undefined,
145-
})
146-
147-
response = await InlineCompletionService.instance.getPaginatedRecommendation(
148-
client,
149-
editor,
150-
triggerType,
151-
config,
152-
autoTriggerType,
153-
event
154-
)
155-
} finally {
156-
this._isRunning = false
157-
this._onSuggestionActionEvent.fire({
158-
editor: editor,
159-
isRunning: false,
160-
triggerType: triggerType,
161-
response: response,
162-
})
163-
}
164-
}
178+
}, traceId)
165179
}
166180
}

packages/core/src/codewhisperer/util/telemetryHelper.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ export class TelemetryHelper {
4646
private timeToFirstRecommendation = 0
4747
private classifierResult?: number = undefined
4848
private classifierThreshold?: number = undefined
49+
// variables for tracking end to end sessions
50+
public traceId: string = 'notSet'
4951

5052
// use this to distinguish DocumentChangeEvent from CWSPR or from other sources
5153
public lastSuggestionInDisplay = ''
@@ -90,6 +92,7 @@ export class TelemetryHelper {
9092
codewhispererSupplementalContextLength: supplementalContextMetadata?.contentsLength,
9193
codewhispererUserGroup: CodeWhispererUserGroupSettings.getUserGroup().toString(),
9294
codewhispererCustomizationArn: getSelectedCustomization().arn,
95+
traceId: this.traceId,
9396
}
9497
telemetry.codewhisperer_serviceInvocation.emit(event)
9598
}
@@ -118,6 +121,7 @@ export class TelemetryHelper {
118121
codewhispererSupplementalContextTimeout: supplementalContextMetadata?.isProcessTimeout,
119122
codewhispererSupplementalContextIsUtg: supplementalContextMetadata?.isUtg,
120123
codewhispererSupplementalContextLength: supplementalContextMetadata?.contentsLength,
124+
traceId: this.traceId,
121125
})
122126
}
123127

@@ -171,6 +175,7 @@ export class TelemetryHelper {
171175
codewhispererSupplementalContextTimeout: supplementalContextMetadata?.isProcessTimeout,
172176
codewhispererSupplementalContextIsUtg: supplementalContextMetadata?.isUtg,
173177
codewhispererSupplementalContextLength: supplementalContextMetadata?.contentsLength,
178+
traceId: this.traceId,
174179
}
175180
telemetry.codewhisperer_userDecision.emit(event)
176181
events.push(event)
@@ -234,6 +239,7 @@ export class TelemetryHelper {
234239
codewhispererSupplementalContextTimeout: supplementalContextMetadata?.isProcessTimeout,
235240
codewhispererSupplementalContextIsUtg: supplementalContextMetadata?.isUtg,
236241
codewhispererSupplementalContextLength: supplementalContextMetadata?.contentsLength,
242+
traceId: this.traceId,
237243
}
238244
return aggregated
239245
}
@@ -299,6 +305,7 @@ export class TelemetryHelper {
299305
codewhispererSupplementalContextStrategyId: supplementalContextMetadata?.strategy,
300306
codewhispererCharactersAccepted: acceptedRecommendationContent.length,
301307
codewhispererFeatureEvaluations: FeatureConfigProvider.instance.getFeatureConfigsTelemetry(),
308+
traceId: this.traceId,
302309
}
303310
telemetry.codewhisperer_userTriggerDecision.emit(aggregated)
304311
this.prevTriggerDecision = this.getAggregatedSuggestionState(this.sessionDecisions)
@@ -386,6 +393,10 @@ export class TelemetryHelper {
386393
}
387394
}
388395

396+
public setTraceId(traceId: string) {
397+
this.traceId = traceId
398+
}
399+
389400
private resetUserTriggerDecisionTelemetry() {
390401
this.sessionDecisions = []
391402
this.triggerChar = ''

packages/core/src/codewhisperer/views/activeStateController.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import { subscribeOnce } from '../../shared/utilities/vsCodeUtils'
1111
import { Container } from '../service/serviceContainer'
1212
import { RecommendationHandler } from '../service/recommendationHandler'
1313
import { cancellableDebounce } from '../../shared/utilities/functionUtils'
14+
import { telemetry } from '../../shared/telemetry'
15+
import { TelemetryHelper } from '../util/telemetryHelper'
1416

1517
export class ActiveStateController implements vscode.Disposable {
1618
private readonly _disposable: vscode.Disposable
@@ -33,7 +35,9 @@ export class ActiveStateController implements vscode.Disposable {
3335
constructor(private readonly container: Container) {
3436
this._disposable = vscode.Disposable.from(
3537
RecommendationService.instance.suggestionActionEvent(async (e) => {
36-
await this.onSuggestionActionEvent(e)
38+
await telemetry.withTraceId(async () => {
39+
await this.onSuggestionActionEvent(e)
40+
}, TelemetryHelper.instance.traceId)
3741
}),
3842
RecommendationHandler.instance.onDidReceiveRecommendation(async (_) => {
3943
await this.onDidReceiveRecommendation()

0 commit comments

Comments
 (0)