Skip to content

Commit a43ed0b

Browse files
authored
feat(telemetry): add request ID to events on failures (#3473)
## Problem No way to connect service-side issues with client-side failures. ## Solution Add `requestId` plus the service name to the current event and any subsequent events.
1 parent ad1e928 commit a43ed0b

File tree

3 files changed

+34
-10
lines changed

3 files changed

+34
-10
lines changed

package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3440,7 +3440,7 @@
34403440
"report": "nyc report --reporter=html --reporter=json"
34413441
},
34423442
"devDependencies": {
3443-
"@aws-toolkits/telemetry": "^1.0.127",
3443+
"@aws-toolkits/telemetry": "^1.0.129",
34443444
"@cspotcode/source-map-support": "^0.8.1",
34453445
"@sinonjs/fake-timers": "^10.0.2",
34463446
"@types/adm-zip": "^0.4.34",

src/shared/awsClientBuilder.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { ServiceConfigurationOptions } from 'aws-sdk/lib/service'
99
import { AwsContext } from './awsContext'
1010
import { DevSettings } from './settings'
1111
import { getUserAgent } from './telemetry/util'
12+
import { telemetry } from './telemetry/telemetry'
1213

1314
// These are not on the public API but are very useful for logging purposes.
1415
// Tests guard against the possibility that these values change unexpectedly.
@@ -131,14 +132,37 @@ export class DefaultAWSClientBuilder implements AWSClientBuilder {
131132

132133
const apiConfig = (opt as { apiConfig?: { metadata?: Record<string, string> } } | undefined)?.apiConfig
133134
const serviceName =
134-
apiConfig?.metadata?.serviceId ?? (type as unknown as { serviceIdentifier?: string }).serviceIdentifier
135+
apiConfig?.metadata?.serviceId?.toLowerCase() ??
136+
(type as unknown as { serviceIdentifier?: string }).serviceIdentifier
137+
135138
if (serviceName) {
136-
opt.endpoint = settings.get('endpoints', {})[serviceName.toLowerCase()] ?? opt.endpoint
139+
opt.endpoint = settings.get('endpoints', {})[serviceName] ?? opt.endpoint
137140
}
138141

139142
const service = new type(opt)
140143
const originalSetup = service.setupRequestListeners.bind(service)
141144

145+
// Record request IDs to the current context, potentially overriding the field if
146+
// multiple API calls are made in the same context. We only do failures as successes
147+
// are generally uninteresting and noisy.
148+
listeners.push(request => {
149+
request.on('error', err => {
150+
if (!err.retryable) {
151+
// TODO: update codegen so `record` enumerates all fields as a flat object instead of
152+
// intersecting all of the definitions
153+
interface RequestData {
154+
requestId?: string
155+
requestServiceType?: string
156+
}
157+
158+
telemetry.record({
159+
requestId: err.requestId,
160+
requestServiceType: serviceName,
161+
} satisfies RequestData as any)
162+
}
163+
})
164+
})
165+
142166
service.setupRequestListeners = (request: Request<any, AWSError>) => {
143167
originalSetup(request)
144168
listeners.forEach(l => l(request as AWS.Request<any, AWSError> & RequestExtras))

0 commit comments

Comments
 (0)