Skip to content

Commit 66a3ca5

Browse files
kzr-at-amazonkzr-at-amazon
andauthored
telemetry(smus): Handle async calls gracefully in telemetry (#8472)
## Problem - sometimes custom metrics are missing from `smus_stopSpace` and `smus_openRemoteConnection` ## Solution - Some telemetry custom variables are fetched via async calls - This calls should gracefully handle async failures, and still being able to record what metrics are available. ### Example - successful async calls ``` 2025-12-29 11:38:25.994 [debug] telemetry: smus_openRemoteConnection { Metadata: { metricId: 'acc0a9b4-e642-4e4f-a2a7-949879fca73d', traceId: '911f58fd-9f63-4a8f-8e87-590d3f46d534', smusAuthMode: 'iam', smusSpaceKey: 'd-5eomwrxzxbim__default-ce003678-576c-4253-a65f-01ef29af4f94', smusDomainRegion: 'us-east-2', smusDomainId: 'dzd-byubiyc1bebgfd', smusProjectId: 'b236u0pytkd02x', smusDomainAccountId: '619071339486', smusProjectAccountId: '619071339486', smusProjectRegion: 'us-east-2', duration: '20598', result: 'Succeeded', awsAccount: 'not-set', awsRegion: 'us-west-2' }, Value: 1, Unit: 'None', Passive: false } ``` ``` 2025-12-29 11:39:28.454 [debug] telemetry: smus_stopSpace { Metadata: { metricId: '743e4212-8d6f-40bf-b2aa-a3ab45b5aa86', traceId: '6bfd857d-cf53-410e-9e38-d1f8b37ec833', smusAuthMode: 'iam', smusSpaceKey: 'd-5eomwrxzxbim__default-ce003678-576c-4253-a65f-01ef29af4f94', smusDomainRegion: 'us-east-2', smusDomainId: 'dzd-byubiyc1bebgfd', smusProjectId: 'b236u0pytkd02x', smusDomainAccountId: '619071339486', smusProjectAccountId: '619071339486', smusProjectRegion: 'us-east-2', duration: '4430', result: 'Succeeded', awsAccount: 'not-set', awsRegion: 'us-west-2' }, Value: 1, Unit: 'None', Passive: false } ``` - failed async calls ``` 2025-12-29 12:00:12.444 [warning] smus: Failed to get project region for telemetry: The security token included in the request is expired ``` ``` 2025-12-29 12:00:15.237 [debug] telemetry: smus_stopSpace { Metadata: { metricId: '52e34dd6-3016-4abc-82cb-2605c2cb7e71', traceId: '8288d8a9-6674-4402-901a-0ebafe57ad1d', smusAuthMode: 'iam', smusSpaceKey: 'd-5eomwrxzxbim__default-ce003678-576c-4253-a65f-01ef29af4f94', smusDomainRegion: 'us-east-2', smusDomainId: 'dzd-byubiyc1bebgfd', smusProjectId: 'b236u0pytkd02x', smusDomainAccountId: '619071339486', smusProjectAccountId: '619071339486', smusProjectRegion: 'not-set', duration: '2973', result: 'Failed', reason: 'ExpiredTokenException', reasonDesc: 'ExpiredTokenException: Failed to stop space default-ce003678-576c-4253-a65f-01ef29af4f94: The security token included in the request is expired | ExpiredTokenException: The security token included in the request is expired', awsAccount: 'not-set', awsRegion: 'us-west-2' }, Value: 1, Unit: 'None', Passive: false } ``` `smusProjectRegion` is set to 'not-set` and the rest of custom metrics are recorded. --- - Treat all work as PUBLIC. Private `feature/x` branches will not be squash-merged at release time. - Your code changes must meet the guidelines in [CONTRIBUTING.md](https://github.com/aws/aws-toolkit-vscode/blob/master/CONTRIBUTING.md#guidelines). - License: I confirm that my contribution is made under the terms of the Apache 2.0 license. Co-authored-by: kzr-at-amazon <build@amazon.com>
1 parent 9083350 commit 66a3ca5

File tree

2 files changed

+63
-53
lines changed

2 files changed

+63
-53
lines changed

packages/core/src/sagemakerunifiedstudio/shared/telemetry.ts

Lines changed: 52 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { ConnectionCredentialsProvider } from '../auth/providers/connectionCrede
2121
import { DataZoneConnection } from './client/datazoneClient'
2222
import { createDZClientBaseOnDomainMode } from '../explorer/nodes/utils'
2323

24+
const notSet = 'not-set'
2425
/**
2526
* Records space telemetry
2627
*/
@@ -30,37 +31,46 @@ export async function recordSpaceTelemetry(
3031
) {
3132
const logger = getLogger('smus')
3233

34+
const parent = node.resource.getParent() as SageMakerUnifiedStudioSpacesParentNode
35+
const authProvider = SmusAuthenticationProvider.fromContext()
36+
const projectId = parent?.getProjectId()
37+
const domainId = parent?.getAuthProvider()?.getDomainId()
38+
39+
span.record({
40+
smusAuthMode: authProvider.activeConnection?.type,
41+
smusSpaceKey: node.resource.DomainSpaceKey,
42+
smusDomainRegion: node.resource.regionCode,
43+
smusDomainId: domainId,
44+
smusProjectId: projectId,
45+
})
46+
3347
try {
34-
const parent = node.resource.getParent() as SageMakerUnifiedStudioSpacesParentNode
35-
const authProvider = SmusAuthenticationProvider.fromContext()
3648
const accountId = await authProvider.getDomainAccountId()
37-
const projectId = parent?.getProjectId()
38-
39-
// Get project account ID and region
40-
let projectAccountId: string | undefined
41-
let projectRegion: string | undefined
49+
span.record({ smusDomainAccountId: accountId })
50+
} catch (err) {
51+
span.record({ smusDomainAccountId: notSet })
52+
logger.warn(`Failed to record domain account Id for telemetry in domain ${domainId}: ${(err as Error).message}`)
53+
}
4254

43-
if (projectId) {
44-
projectAccountId = await authProvider.getProjectAccountId(projectId)
55+
if (projectId) {
56+
try {
57+
const projectAccountId = await authProvider.getProjectAccountId(projectId)
58+
span.record({ smusProjectAccountId: projectAccountId })
59+
} catch (err) {
60+
span.record({ smusProjectAccountId: notSet })
61+
logger.warn(
62+
`Failed to record project account Id for telemetry in domain ${domainId}: ${(err as Error).message}`
63+
)
64+
}
4565

46-
// Get project region from tooling environment
66+
try {
4767
const dzClient = await createDZClientBaseOnDomainMode(authProvider)
4868
const toolingEnv = await dzClient.getToolingEnvironment(projectId)
49-
projectRegion = toolingEnv.awsAccountRegion
69+
span.record({ smusProjectRegion: toolingEnv.awsAccountRegion })
70+
} catch (err) {
71+
span.record({ smusProjectRegion: notSet })
72+
logger.warn(`Failed to get project region for telemetry: ${(err as Error).message}`)
5073
}
51-
52-
span.record({
53-
smusAuthMode: authProvider.activeConnection?.type,
54-
smusSpaceKey: node.resource.DomainSpaceKey,
55-
smusDomainRegion: node.resource.regionCode,
56-
smusDomainId: parent?.getAuthProvider()?.getDomainId(),
57-
smusDomainAccountId: accountId,
58-
smusProjectId: projectId,
59-
smusProjectAccountId: projectAccountId,
60-
smusProjectRegion: projectRegion,
61-
})
62-
} catch (err) {
63-
logger.error(`Failed to record space telemetry: ${(err as Error).message}`)
6474
}
6575
}
6676

@@ -90,6 +100,7 @@ export async function recordAuthTelemetry(
90100
smusDomainAccountId: accountId,
91101
})
92102
} catch (err) {
103+
span.record({ smusDomainAccountId: notSet })
93104
logger.error(
94105
`Failed to record Domain AccountId in data connection telemetry for domain ${domainId} in region ${region}: ${err}`
95106
)
@@ -106,23 +117,25 @@ export async function recordDataConnectionTelemetry(
106117
) {
107118
const logger = getLogger('smus')
108119

120+
const isInSmusSpace = getContext('aws.smus.inSmusSpaceEnvironment')
121+
const authProvider = SmusAuthenticationProvider.fromContext()
122+
123+
span.record({
124+
smusAuthMode: authProvider.activeConnection?.type,
125+
smusToolkitEnv: isInSmusSpace ? 'smus_space' : 'local',
126+
smusDomainId: connection.domainId,
127+
smusProjectId: connection.projectId,
128+
smusConnectionId: connection.connectionId,
129+
smusConnectionType: connection.type,
130+
smusProjectRegion: connection.location?.awsRegion,
131+
smusProjectAccountId: connection.location?.awsAccountId,
132+
})
133+
109134
try {
110-
const isInSmusSpace = getContext('aws.smus.inSmusSpaceEnvironment')
111-
const authProvider = SmusAuthenticationProvider.fromContext()
112135
const accountId = await connectionCredentialsProvider.getDomainAccountId()
113-
114-
span.record({
115-
smusAuthMode: authProvider.activeConnection?.type,
116-
smusToolkitEnv: isInSmusSpace ? 'smus_space' : 'local',
117-
smusDomainId: connection.domainId,
118-
smusDomainAccountId: accountId,
119-
smusProjectId: connection.projectId,
120-
smusConnectionId: connection.connectionId,
121-
smusConnectionType: connection.type,
122-
smusProjectRegion: connection.location?.awsRegion,
123-
smusProjectAccountId: connection.location?.awsAccountId,
124-
})
136+
span.record({ smusDomainAccountId: accountId })
125137
} catch (err) {
126-
logger.error(`Failed to record data connection telemetry: ${(err as Error).message}`)
138+
span.record({ smusDomainAccountId: notSet })
139+
logger.warn(`Failed to record domain account ID for data connection telemetry: ${(err as Error).message}`)
127140
}
128141
}

packages/core/src/test/sagemakerunifiedstudio/testUtils.ts

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -65,25 +65,22 @@ export function createMockUnauthenticatedAuthProvider(): any {
6565
Creates a mock space node for SageMaker Unified Studio tests
6666
*/
6767
export function createMockSpaceNode(): any {
68+
const mockParent = {
69+
getAuthProvider: sinon.stub().returns({
70+
activeConnection: { domainId: 'test-domain' },
71+
getDomainAccountId: sinon.stub().resolves('123456789012'),
72+
getDomainId: sinon.stub().returns('test-domain'),
73+
}),
74+
getProjectId: sinon.stub().returns('test-project'),
75+
}
76+
6877
return {
6978
resource: {
7079
sageMakerClient: {},
7180
DomainSpaceKey: 'test-space-key',
7281
regionCode: 'us-east-1',
73-
getParent: sinon.stub().returns({
74-
getAuthProvider: sinon.stub().returns({
75-
activeConnection: { domainId: 'test-domain' },
76-
getDomainAccountId: sinon.stub().resolves('123456789012'),
77-
}),
78-
getProjectId: sinon.stub().returns('test-project'),
79-
}),
82+
getParent: sinon.stub().returns(mockParent),
8083
},
81-
getParent: sinon.stub().returns({
82-
getAuthProvider: sinon.stub().returns({
83-
activeConnection: { domainId: 'test-domain' },
84-
getDomainAccountId: sinon.stub().resolves('123456789012'),
85-
}),
86-
getProjectId: sinon.stub().returns('test-project'),
87-
}),
84+
getParent: sinon.stub().returns(mockParent),
8885
}
8986
}

0 commit comments

Comments
 (0)