Skip to content

Commit edef43c

Browse files
kaizenccgithub-actions
andauthored
chore(cli): funnel (#760)
A funnel is a combination sink class. It will be used later to record telemetry both to file _and_ send to endpoint. That version will be used in the situation where telemetry is turned on _and_ `--telemetry-file` is set. --- By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license --------- Signed-off-by: github-actions <[email protected]> Co-authored-by: github-actions <[email protected]>
1 parent a94b241 commit edef43c

File tree

6 files changed

+348
-193
lines changed

6 files changed

+348
-193
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { ToolkitError } from '@aws-cdk/toolkit-lib';
2+
import type { TelemetrySchema } from '../schema';
3+
import type { ITelemetrySink } from './sink-interface';
4+
5+
export interface FunnelProps {
6+
readonly sinks: ITelemetrySink[];
7+
}
8+
9+
/**
10+
* A funnel is a combination of one or more sinks.
11+
* The sink functions are executed in parallel, and a maximum of 5
12+
* sinks are supported per funnel.
13+
*/
14+
export class Funnel {
15+
private readonly sinks: ITelemetrySink[];
16+
17+
constructor(props: FunnelProps) {
18+
if (props.sinks.length > 5) {
19+
throw new ToolkitError(`Funnel class supports a maximum of 5 parallel sinks, got ${props.sinks.length} sinks.`);
20+
}
21+
22+
this.sinks = props.sinks;
23+
}
24+
25+
public async emit(event: TelemetrySchema): Promise<void> {
26+
// Funnel class enforces a maximum of 5 parallel sinks
27+
// eslint-disable-next-line @cdklabs/promiseall-no-unbounded-parallelism
28+
await Promise.all(this.sinks.map(sink => sink.emit(event)));
29+
}
30+
31+
public async flush(): Promise<void> {
32+
// Funnel class enforces a maximum of 5 parallel sinks
33+
// eslint-disable-next-line @cdklabs/promiseall-no-unbounded-parallelism
34+
await Promise.all(this.sinks.map(sink => sink.flush()));
35+
}
36+
}

packages/aws-cdk/test/cli/telemetry/sink/endpoint-sink.test.ts

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,14 @@
11
import * as https from 'https';
2+
import { createTestEvent } from './util';
23
import { IoHelper } from '../../../../lib/api-private';
34
import { CliIoHost } from '../../../../lib/cli/io-host';
4-
import type { EventType, TelemetrySchema } from '../../../../lib/cli/telemetry/schema';
55
import { EndpointTelemetrySink } from '../../../../lib/cli/telemetry/sink/endpoint-sink';
66

77
// Mock the https module
88
jest.mock('https', () => ({
99
request: jest.fn(),
1010
}));
1111

12-
// Helper function to create a test event
13-
function createTestEvent(eventType: EventType, properties: Record<string, any> = {}): TelemetrySchema {
14-
return {
15-
identifiers: {
16-
cdkCliVersion: '1.0.0',
17-
telemetryVersion: '1.0.0',
18-
sessionId: 'test-session',
19-
eventId: `test-event-${eventType}`,
20-
installationId: 'test-installation',
21-
timestamp: new Date().toISOString(),
22-
},
23-
event: {
24-
state: 'SUCCEEDED',
25-
eventType,
26-
command: {
27-
path: ['test'],
28-
parameters: {},
29-
config: properties,
30-
},
31-
},
32-
environment: {
33-
os: {
34-
platform: 'test',
35-
release: 'test',
36-
},
37-
ci: false,
38-
nodeVersion: process.version,
39-
},
40-
project: {},
41-
duration: {
42-
total: 0,
43-
},
44-
};
45-
}
46-
4712
describe('EndpointTelemetrySink', () => {
4813
let ioHost: CliIoHost;
4914

packages/aws-cdk/test/cli/telemetry/sink/file-sink.test.ts

Lines changed: 4 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import * as os from 'os';
22
import * as path from 'path';
33
import * as fs from 'fs-extra';
4+
import { createTestEvent } from './util';
45
import { IoHelper } from '../../../../lib/api-private';
56
import { CliIoHost } from '../../../../lib/cli/io-host';
6-
import type { TelemetrySchema } from '../../../../lib/cli/telemetry/schema';
77
import { FileTelemetrySink } from '../../../../lib/cli/telemetry/sink/file-sink';
88

99
describe('FileTelemetrySink', () => {
@@ -32,37 +32,7 @@ describe('FileTelemetrySink', () => {
3232

3333
test('saves data to a file', async () => {
3434
// GIVEN
35-
const testEvent: TelemetrySchema = {
36-
identifiers: {
37-
cdkCliVersion: '1.0.0',
38-
telemetryVersion: '1.0.0',
39-
sessionId: 'test-session',
40-
eventId: 'test-event',
41-
installationId: 'test-installation',
42-
timestamp: new Date().toISOString(),
43-
},
44-
event: {
45-
state: 'SUCCEEDED',
46-
eventType: 'INVOKE',
47-
command: {
48-
path: ['test'],
49-
parameters: {},
50-
config: { context: { foo: true } },
51-
},
52-
},
53-
environment: {
54-
os: {
55-
platform: 'test',
56-
release: 'test',
57-
},
58-
ci: false,
59-
nodeVersion: process.version,
60-
},
61-
project: {},
62-
duration: {
63-
total: 0,
64-
},
65-
};
35+
const testEvent = createTestEvent('INVOKE', { context: { foo: true } });
6636
const client = new FileTelemetrySink({ logFilePath, ioHost });
6737

6838
// WHEN
@@ -76,37 +46,7 @@ describe('FileTelemetrySink', () => {
7646

7747
test('appends data to a file', async () => {
7848
// GIVEN
79-
const testEvent: TelemetrySchema = {
80-
identifiers: {
81-
cdkCliVersion: '1.0.0',
82-
telemetryVersion: '1.0.0',
83-
sessionId: 'test-session',
84-
eventId: 'test-event',
85-
installationId: 'test-installation',
86-
timestamp: new Date().toISOString(),
87-
},
88-
event: {
89-
state: 'SUCCEEDED',
90-
eventType: 'INVOKE',
91-
command: {
92-
path: ['test'],
93-
parameters: {},
94-
config: { context: { foo: true } },
95-
},
96-
},
97-
environment: {
98-
os: {
99-
platform: 'test',
100-
release: 'test',
101-
},
102-
ci: false,
103-
nodeVersion: process.version,
104-
},
105-
project: {},
106-
duration: {
107-
total: 0,
108-
},
109-
};
49+
const testEvent = createTestEvent('INVOKE', { context: { foo: true } });
11050
const client = new FileTelemetrySink({ logFilePath, ioHost });
11151

11252
// WHEN
@@ -130,37 +70,7 @@ describe('FileTelemetrySink', () => {
13070

13171
test('handles errors gracefully and logs to trace without throwing', async () => {
13272
// GIVEN
133-
const testEvent: TelemetrySchema = {
134-
identifiers: {
135-
cdkCliVersion: '1.0.0',
136-
telemetryVersion: '1.0.0',
137-
sessionId: 'test-session',
138-
eventId: 'test-event',
139-
installationId: 'test-installation',
140-
timestamp: new Date().toISOString(),
141-
},
142-
event: {
143-
state: 'SUCCEEDED',
144-
eventType: 'INVOKE',
145-
command: {
146-
path: ['test'],
147-
parameters: {},
148-
config: { context: { foo: true } },
149-
},
150-
},
151-
environment: {
152-
os: {
153-
platform: 'test',
154-
release: 'test',
155-
},
156-
ci: false,
157-
nodeVersion: process.version,
158-
},
159-
project: {},
160-
duration: {
161-
total: 0,
162-
},
163-
};
73+
const testEvent = createTestEvent('INVOKE', { context: { foo: true } });
16474

16575
// Create a mock IoHelper with trace spy
16676
const traceSpy = jest.fn();

0 commit comments

Comments
 (0)