Skip to content

feat(cli): telemetry event deploy #698

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 139 commits into from
Jul 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
139 commits
Select commit Hold shift + click to select a range
0c1c0b3
chore(cli): telemetry client
kaizencc Jun 9, 2025
2fe74df
docs
kaizencc Jun 9, 2025
c6bf5f4
wip
kaizencc Jun 13, 2025
e91e7e3
use interfaces and fix tests
kaizencc Jun 13, 2025
0d33ac5
add schema and pr feedback
kaizencc Jun 16, 2025
7d5a19a
feat(cli): telemetry for list
kaizencc Jun 18, 2025
41a461b
Merge branch 'main' into conroy/list
kaizencc Jun 18, 2025
c380240
Merge branch 'main' into conroy/basic-telemetry-client
kaizencc Jun 18, 2025
e51d30d
change to parsed url
kaizencc Jun 18, 2025
9d980d5
readonly
kaizencc Jun 18, 2025
d8dd12f
Merge branch 'conroy/basic-telemetry-client' into conroy/list
kaizencc Jun 18, 2025
9126147
Merge branch 'main' into conroy/basic-telemetry-client
kaizencc Jun 19, 2025
ab560fd
small change
kaizencc Jun 19, 2025
4e361ae
retries implemented, not yet tested
kaizencc Jun 19, 2025
69e63cd
add commented out test
kaizencc Jun 19, 2025
da20533
Merge branch 'conroy/basic-telemetry-client' into conroy/list
kaizencc Jun 19, 2025
ca3f172
refactor list telemetry, still wip
kaizencc Jun 20, 2025
3b0082e
1 line change
kaizencc Jun 20, 2025
8824e28
add message code
kaizencc Jun 20, 2025
f7cb38a
add failed synth
kaizencc Jun 20, 2025
8760b44
Merge branch 'main' into conroy/basic-telemetry-client
kaizencc Jun 21, 2025
ece2874
fixup sanitation"
kaizencc Jun 23, 2025
4dea47d
pr feedback
kaizencc Jun 23, 2025
3dbbe62
add proxy support, better retries, test succeeds
kaizencc Jun 25, 2025
feaf376
lint
kaizencc Jun 25, 2025
83ebd08
lints
kaizencc Jun 25, 2025
4b8397b
Merge branch 'conroy/basic-telemetry-client' into conroy/list
kaizencc Jun 25, 2025
cf285bb
wip
kaizencc Jun 25, 2025
2c8191b
reworked with iohost
kaizencc Jun 26, 2025
6c977b6
include spans
kaizencc Jun 26, 2025
56f23e5
force not ci in tests
kaizencc Jun 26, 2025
079bbc5
Merge branch 'main' into conroy/basic-telemetry-client
kaizencc Jun 26, 2025
8e43ba7
Merge branch 'conroy/basic-telemetry-client' into conroy/list
kaizencc Jun 26, 2025
9dd1580
refactors from friday are in a working state
kaizencc Jun 30, 2025
55a4a73
add cdk library version
kaizencc Jun 30, 2025
1041bf8
collect telemetry
kaizencc Jun 30, 2025
635d6b7
Merge branch 'main' into conroy/basic-telemetry-client
kaizencc Jun 30, 2025
18d9349
Merge branch 'main' into conroy/basic-telemetry-client
kaizencc Jul 1, 2025
1811c9a
Merge branch 'conroy/basic-telemetry-client' into conroy/list
kaizencc Jul 1, 2025
ea4720c
Merge branch 'main' into conroy/basic-telemetry-client
kaizencc Jul 2, 2025
b9c0d6d
Merge branch 'conroy/basic-telemetry-client' into conroy/list
kaizencc Jul 2, 2025
46cc2c8
remove circular dependencies
kaizencc Jul 2, 2025
76a19ff
diff tests need to not depend on message order
kaizencc Jul 2, 2025
2433e3e
update type registry name
kaizencc Jul 2, 2025
b30d188
can collect telemetry
kaizencc Jul 2, 2025
fe47576
callback function on crtl-c
kaizencc Jul 2, 2025
4bf3be9
Merge branch 'main' into conroy/basic-telemetry-client
kaizencc Jul 2, 2025
359a442
telemetry interface includes flush
kaizencc Jul 2, 2025
c20ad8b
Merge branch 'conroy/basic-telemetry-client' into conroy/list
kaizencc Jul 2, 2025
54109d6
rename
kaizencc Jul 2, 2025
334b9dd
lint
kaizencc Jul 2, 2025
39152d3
Merge branch 'conroy/basic-telemetry-client' into conroy/list
kaizencc Jul 2, 2025
fbd6dd6
small fixes
kaizencc Jul 2, 2025
70fa3e3
minor enhancements
kaizencc Jul 2, 2025
e02a283
wip
kaizencc Jul 2, 2025
25dec4a
pr feedback
kaizencc Jul 2, 2025
5628ed9
trace
kaizencc Jul 2, 2025
cc8c6dd
pr feedback
kaizencc Jul 2, 2025
9433b36
tests for collect-telemetry
kaizencc Jul 2, 2025
72c862e
lint
kaizencc Jul 2, 2025
d3c745c
test for installation ids
kaizencc Jul 2, 2025
da64d2b
library-version tests
kaizencc Jul 2, 2025
b007f0e
library version tests
kaizencc Jul 2, 2025
9caf42e
refactor telemetry session
kaizencc Jul 3, 2025
ad0e6cd
minors
kaizencc Jul 3, 2025
c7d365a
renames
kaizencc Jul 3, 2025
fb85dfa
Merge branch 'conroy/basic-telemetry-client' into conroy/list
kaizencc Jul 3, 2025
e139111
Merge branch 'main' into conroy/list
kaizencc Jul 3, 2025
27ea7e6
fix merge
kaizencc Jul 3, 2025
f74bb90
small updates
kaizencc Jul 3, 2025
d79756f
fix stupid await
kaizencc Jul 3, 2025
80fad80
sanitize tests
kaizencc Jul 3, 2025
e087b50
accountid test
kaizencc Jul 3, 2025
66bb8c1
region fetcher tests
kaizencc Jul 3, 2025
64b5fa2
fix tests from merge
kaizencc Jul 7, 2025
b5d0f32
fix build
kaizencc Jul 7, 2025
b2b56d3
Merge branch 'main' into conroy/list
kaizencc Jul 7, 2025
1adc88e
session unit tests
kaizencc Jul 7, 2025
541eeb4
Update packages/aws-cdk/test/commands/diff.test.ts
kaizencc Jul 7, 2025
59aecf1
iohost unit tests
kaizencc Jul 7, 2025
af1bbbb
Update packages/aws-cdk/lib/init-templates/.init-version.json
kaizencc Jul 7, 2025
6a86ee3
Update .recommended-feature-flags.json
kaizencc Jul 7, 2025
6427847
Update .recommended-feature-flags.json
kaizencc Jul 7, 2025
effed08
s
kaizencc Jul 7, 2025
27fa7de
fix
kaizencc Jul 8, 2025
75b6490
Merge branch 'main' into conroy/list
kaizencc Jul 8, 2025
9dc5a68
update test
kaizencc Jul 8, 2025
8341898
Apply suggestions from code review
kaizencc Jul 8, 2025
0df012b
chore(cli): deploy telemetry event
kaizencc Jul 8, 2025
38243d3
Update packages/aws-cdk/lib/cli/cdk-toolkit.ts
kaizencc Jul 8, 2025
aa169c7
update comment
kaizencc Jul 9, 2025
e783eb2
ci file
kaizencc Jul 9, 2025
4fad6c6
Merge branch 'main' into conroy/list
kaizencc Jul 9, 2025
31f5a92
refactors
kaizencc Jul 9, 2025
670a289
update-test
kaizencc Jul 10, 2025
8ea3e65
merge
kaizencc Jul 10, 2025
0a15701
delete previously deleted file
kaizencc Jul 10, 2025
d193044
fix merge
kaizencc Jul 10, 2025
c694d99
telemetry to file
kaizencc Jul 10, 2025
2b51b13
update
kaizencc Jul 10, 2025
d17faf7
add cli integ test for telemetry file
kaizencc Jul 10, 2025
702f02f
Merge branch 'conroy/list' into conroy/deploy
kaizencc Jul 10, 2025
1c94d1b
Merge branch 'main' into conroy/list
kaizencc Jul 11, 2025
1e138ac
update version and fix tests
kaizencc Jul 11, 2025
3b0917d
chore: self mutation
invalid-email-address Jul 11, 2025
0feda68
Merge branch 'conroy/list' into conroy/deploy
kaizencc Jul 11, 2025
956aa9f
Merge branch 'main' into conroy/list
kaizencc Jul 11, 2025
e6b9cda
add deploy integ test
kaizencc Jul 11, 2025
cfc070d
Merge branch 'main' into conroy/list
kaizencc Jul 11, 2025
3f850e0
integ test for failure
kaizencc Jul 11, 2025
2edd715
chore: self mutation
invalid-email-address Jul 11, 2025
e317acd
Merge branch 'main' into conroy/list
kaizencc Jul 16, 2025
f29dec5
Merge branch 'conroy/list' into conroy/deploy
kaizencc Jul 16, 2025
89cebdf
fix errors
kaizencc Jul 16, 2025
26782dc
pr feedback
kaizencc Jul 16, 2025
d8ad347
prune integ test
kaizencc Jul 16, 2025
bd0f7c9
fix build
kaizencc Jul 16, 2025
9637f69
chore: self mutation
invalid-email-address Jul 16, 2025
17d4d19
Merge branch 'main' into conroy/list
kaizencc Jul 18, 2025
c53f310
Merge branch 'main' into conroy/list
iliapolo Jul 20, 2025
b37c6dd
build
iliapolo Jul 20, 2025
23501c1
Merge branch 'conroy/list' into conroy/deploy
kaizencc Jul 21, 2025
d583c59
chore: self mutation
invalid-email-address Jul 21, 2025
30e054b
pr feedback
kaizencc Jul 21, 2025
f36edc8
more pr feedback
kaizencc Jul 21, 2025
c933608
remove config for now
kaizencc Jul 21, 2025
136546b
final pr feedbacks
kaizencc Jul 21, 2025
9c5ee46
Merge branch 'conroy/list' into conroy/deploy
kaizencc Jul 21, 2025
7fb93b9
lint
kaizencc Jul 21, 2025
d4c367f
Merge branch 'conroy/list' into conroy/deploy
kaizencc Jul 21, 2025
c0cc652
fix test
kaizencc Jul 21, 2025
3f56aeb
Merge branch 'main' into conroy/deploy
kaizencc Jul 23, 2025
3ec9bd6
fix merge
kaizencc Jul 23, 2025
24ad9cb
chore: self mutation
invalid-email-address Jul 23, 2025
b86bde4
fix error
kaizencc Jul 23, 2025
250f465
chore: self mutation
invalid-email-address Jul 23, 2025
da47ec7
Merge branch 'main' into conroy/deploy
kaizencc Jul 23, 2025
3cbd758
Merge branch 'main' into conroy/deploy
iliapolo Jul 23, 2025
7c96ef1
Merge branch 'main' into conroy/deploy
kaizencc Jul 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/@aws-cdk-testing/cli-integ/lib/with-cdk-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ export interface CdkCliOptions extends ShellOptions {
options?: string[];
neverRequireApproval?: boolean;
verbose?: boolean;
telemetryFile?: string;
}

export interface CdkDestroyCliOptions extends CdkCliOptions {
Expand Down Expand Up @@ -383,6 +384,7 @@ export class TestFixture extends ShellHelper {
// use events because bar renders bad in tests
'--progress', 'events',
...(skipStackRename ? stackNames : this.fullStackName(stackNames)),
...(options.telemetryFile ? ['--unstable=telemetry', `--telemetry-file=${options.telemetryFile}`] : []),
];
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import * as path from 'path';
import * as fs from 'fs-extra';
import { integTest, withDefaultFixture } from '../../../lib';

jest.setTimeout(2 * 60 * 60_000); // Includes the time to acquire locks, worst-case single-threaded runtime

integTest(
'cdk deploy with telemetry data',
withDefaultFixture(async (fixture) => {
const telemetryFile = path.join(fixture.integTestDir, 'telemetry.json');

// Deploy stack while collecting telemetry
await fixture.cdkDeploy('test-1', {
telemetryFile,
});
const json = fs.readJSONSync(telemetryFile);
expect(json).toEqual([
expect.objectContaining({
event: expect.objectContaining({
command: expect.objectContaining({
path: ['deploy', '$STACKS_1'],
}),
state: 'SUCCEEDED',
eventType: 'SYNTH',
}),
identifiers: expect.objectContaining({
eventId: expect.stringContaining(':1'),
}),
}),
expect.objectContaining({
event: expect.objectContaining({
command: expect.objectContaining({
path: ['deploy', '$STACKS_1'],
}),
state: 'SUCCEEDED',
eventType: 'DEPLOY',
}),
identifiers: expect.objectContaining({
eventId: expect.stringContaining(':2'),
}),
}),
expect.objectContaining({
event: expect.objectContaining({
command: expect.objectContaining({
path: ['deploy', '$STACKS_1'],
}),
state: 'SUCCEEDED',
eventType: 'INVOKE',
}),
identifiers: expect.objectContaining({
eventId: expect.stringContaining(':3'),
}),
}),
]);
fs.unlinkSync(telemetryFile);
}),
);
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,3 @@ integTest(
fs.unlinkSync(telemetryFile);
}),
);

18 changes: 16 additions & 2 deletions packages/aws-cdk/lib/cli/cdk-toolkit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ import {
validateSnsTopicArn,
} from '../util';
import { canCollectTelemetry } from './telemetry/collect-telemetry';
import { cdkCliErrorName } from './telemetry/error';
import { CLI_PRIVATE_SPAN } from './telemetry/messages';
import type { ErrorDetails } from './telemetry/schema';

// Must use a require() otherwise esbuild complains about calling a namespace
// eslint-disable-next-line @typescript-eslint/no-require-imports,@typescript-eslint/consistent-type-imports
Expand Down Expand Up @@ -519,12 +522,15 @@ export class CdkToolkit {
const stackIndex = stacks.indexOf(stack) + 1;
await this.ioHost.asIoHelper().defaults.info(`${chalk.bold(stack.displayName)}: deploying... [${stackIndex}/${stackCollection.stackCount}]`);
const startDeployTime = new Date().getTime();

let tags = options.tags;
if (!tags || tags.length === 0) {
tags = tagsForStack(stack);
}

// There is already a startDeployTime constant, but that does not work with telemetry.
// We should integrate the two in the future
const deploySpan = await this.ioHost.asIoHelper().span(CLI_PRIVATE_SPAN.DEPLOY).begin({});
let error: ErrorDetails | undefined;
let elapsedDeployTime = 0;
try {
let deployResult: SuccessfulDeployStackResult | undefined;
Expand Down Expand Up @@ -638,10 +644,18 @@ export class CdkToolkit {
} catch (e: any) {
// It has to be exactly this string because an integration test tests for
// "bold(stackname) failed: ResourceNotReady: <error>"
throw new ToolkitError(
const wrappedError = new ToolkitError(
[`❌ ${chalk.bold(stack.stackName)} failed:`, ...(e.name ? [`${e.name}:`] : []), formatErrorMessage(e)].join(' '),
);

error = {
name: cdkCliErrorName(wrappedError.name),
};

throw wrappedError;
} finally {
await deploySpan.end({ error });

if (options.cloudWatchLogMonitor) {
const foundLogGroupsResult = await findCloudWatchLogGroups(this.props.sdkProvider, asIoHelper(this.ioHost, 'deploy'), stack);
options.cloudWatchLogMonitor.addLogGroups(
Expand Down
11 changes: 7 additions & 4 deletions packages/aws-cdk/lib/cli/io-host/cli-io-host.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import type { IoHelper, ActivityPrinterProps, IActivityPrinter } from '../../../
import { asIoHelper, IO, isMessageRelevantForLevel, CurrentActivityPrinter, HistoryActivityPrinter } from '../../../lib/api-private';
import { StackActivityProgress } from '../../commands/deploy';
import { FileTelemetrySink } from '../telemetry/file-sink';
import { CLI_PRIVATE_IO } from '../telemetry/messages';
import type { EventResult } from '../telemetry/messages';
import { CLI_PRIVATE_IO, CLI_TELEMETRY_CODES } from '../telemetry/messages';
import type { EventType } from '../telemetry/schema';
import { TelemetrySession } from '../telemetry/session';
import { isCI } from '../util/ci';
Expand Down Expand Up @@ -552,12 +553,12 @@ function targetStreamObject(x: TargetStream): NodeJS.WriteStream | undefined {
}
}

function isNoticesMessage(msg: IoMessage<unknown>) {
function isNoticesMessage(msg: IoMessage<unknown>): msg is IoMessage<void> {
return IO.CDK_TOOLKIT_I0100.is(msg) || IO.CDK_TOOLKIT_W0101.is(msg) || IO.CDK_TOOLKIT_E0101.is(msg) || IO.CDK_TOOLKIT_I0101.is(msg);
}

function isTelemetryMessage(msg: IoMessage<unknown>) {
return CLI_PRIVATE_IO.CDK_CLI_I1001.is(msg) || CLI_PRIVATE_IO.CDK_CLI_I2001.is(msg);
function isTelemetryMessage(msg: IoMessage<unknown>): msg is IoMessage<EventResult> {
return CLI_TELEMETRY_CODES.some((c) => c.is(msg));
}

function getEventType(msg: IoMessage<unknown>): EventType {
Expand All @@ -566,6 +567,8 @@ function getEventType(msg: IoMessage<unknown>): EventType {
return 'SYNTH';
case CLI_PRIVATE_IO.CDK_CLI_I2001.code:
return 'INVOKE';
case CLI_PRIVATE_IO.CDK_CLI_I3001.code:
return 'DEPLOY';
default:
throw new ToolkitError(`Unrecognized Telemetry Message Code: ${msg.code}`);
}
Expand Down
21 changes: 21 additions & 0 deletions packages/aws-cdk/lib/cli/telemetry/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ export const CLI_PRIVATE_IO = {
description: 'Command has finished executing',
interface: 'EventResult',
}),
CDK_CLI_I3000: make.trace<EventStart>({
code: 'CDK_CLI_I3000',
description: 'Deploy has started',
interface: 'EventStart',
}),
CDK_CLI_I3001: make.trace<EventResult>({
code: 'CDK_CLI_I3001',
description: 'Deploy has finished',
interface: 'EventResult',
}),
};

/**
Expand All @@ -50,4 +60,15 @@ export const CLI_PRIVATE_SPAN = {
start: CLI_PRIVATE_IO.CDK_CLI_I2000,
end: CLI_PRIVATE_IO.CDK_CLI_I2001,
},
DEPLOY: {
name: 'Deploy',
start: CLI_PRIVATE_IO.CDK_CLI_I3000,
end: CLI_PRIVATE_IO.CDK_CLI_I3001,
},
} satisfies Record<string, SpanDefinition<any, any>>;

export const CLI_TELEMETRY_CODES = [
CLI_PRIVATE_IO.CDK_CLI_I1001,
CLI_PRIVATE_IO.CDK_CLI_I2001,
CLI_PRIVATE_IO.CDK_CLI_I3001,
];
2 changes: 1 addition & 1 deletion packages/aws-cdk/lib/cli/telemetry/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ interface SessionEvent {
readonly command: Command;
}

export type EventType = 'SYNTH' | 'INVOKE';
export type EventType = 'SYNTH' | 'INVOKE' | 'DEPLOY';
export type State = 'ABORTED' | 'FAILED' | 'SUCCEEDED';
interface Event extends SessionEvent {
readonly state: State;
Expand Down
Loading