@@ -17,159 +17,171 @@ import {
1717 RESOURCE_NAME_PREFIX ,
1818} from './constants.js' ;
1919
20- describe ( 'Tracer E2E tests, decorator instrumentation' , ( ) => {
21- const testStack = new TestStack ( {
22- stackNameProps : {
23- stackNamePrefix : RESOURCE_NAME_PREFIX ,
24- testName : 'Decorator' ,
25- } ,
26- } ) ;
27-
28- // Location of the lambda function code
29- const lambdaFunctionCodeFilePath = join (
30- __dirname ,
31- 'decorator.test.functionCode.ts'
32- ) ;
33- const startTime = new Date ( ) ;
34-
35- const testTable = new TestDynamodbTable (
36- testStack ,
37- { } ,
38- {
39- nameSuffix : 'TestTable' ,
40- }
41- ) ;
42-
43- const fnDecorator = new TestNodejsFunction (
44- testStack ,
45- {
46- entry : lambdaFunctionCodeFilePath ,
47- environment : {
48- TEST_TABLE_NAME : testTable . tableName ,
49- POWERTOOLS_SERVICE_NAME : 'Decorator' ,
50- } ,
51- } ,
52- {
53- nameSuffix : 'Decorator' ,
54- }
55- ) ;
56- testTable . grantWriteData ( fnDecorator ) ;
57-
58- const invocationCount = 2 ;
59- let traceData : EnrichedXRayTraceDocumentParsed [ ] = [ ] ;
60-
61- beforeAll ( async ( ) => {
62- // Deploy the stack
63- await testStack . deploy ( ) ;
64-
65- // Get the actual function names from the stack outputs
66- const fnNameDecorator = testStack . findAndGetStackOutputValue ( 'Decorator' ) ;
67-
68- // Act
69- await invokeAllTestCases ( fnNameDecorator , invocationCount ) ;
70- traceData = await getTraces ( {
71- startTime,
72- resourceName : fnNameDecorator ,
73- expectedTracesCount : invocationCount ,
74- /**
75- * The trace should have 4 segments:
76- * 1. Lambda Context (AWS::Lambda)
77- * 2. Lambda Function (AWS::Lambda::Function)
78- * 4. DynamoDB (AWS::DynamoDB)
79- * 4. Remote call (docs.aws.amazon.com)
80- */
81- expectedSegmentsCount : 4 ,
82- } ) ;
83- } ) ;
84-
85- afterAll ( async ( ) => {
86- if ( ! process . env . DISABLE_TEARDOWN ) {
87- await testStack . destroy ( ) ;
88- }
89- } ) ;
90-
91- it ( 'should generate all trace data correctly' , ( ) => {
92- // Assess
93- const mainSubsegment = traceData [ 0 ] ;
94- const { subsegments, annotations, metadata } = mainSubsegment ;
95-
96- // Check the main segment name
97- expect ( mainSubsegment . name ) . toBe ( '## index.handler' ) ;
98-
99- // Check the subsegments of the main segment
100- expect ( subsegments . size ) . toBe ( 3 ) ;
101-
102- // Check remote call subsegment
103- expect ( subsegments . has ( 'docs.aws.amazon.com' ) ) . toBe ( true ) ;
104- const httpSubsegment = subsegments . get ( 'docs.aws.amazon.com' ) ;
105- expect ( httpSubsegment ?. namespace ) . toBe ( 'remote' ) ;
106- expect ( httpSubsegment ?. http ?. request ?. url ) . toEqual (
107- 'https://docs.aws.amazon.com/powertools/typescript/latest/'
108- ) ;
109- expect ( httpSubsegment ?. http ?. request ?. method ) . toBe ( 'GET' ) ;
110- expect ( httpSubsegment ?. http ?. response ?. status ) . toEqual ( expect . any ( Number ) ) ;
111- expect ( httpSubsegment ?. http ?. response ?. status ) . toEqual ( expect . any ( Number ) ) ;
112-
113- // Check the custom subsegment name & metadata
114- expect ( subsegments . has ( expectedCustomSubSegmentName ) ) . toBe ( true ) ;
115- expect (
116- subsegments . get ( expectedCustomSubSegmentName ) ?. metadata
117- ) . toStrictEqual ( {
118- Decorator : {
119- 'myMethod response' : expectedCustomResponseValue ,
20+ describe . each ( [
21+ { outputFormat : 'CJS' as const } ,
22+ { outputFormat : 'ESM' as const } ,
23+ ] ) (
24+ 'Tracer E2E tests, decorator instrumentation ($outputFormat)' ,
25+ ( { outputFormat } ) => {
26+ const testStack = new TestStack ( {
27+ stackNameProps : {
28+ stackNamePrefix : RESOURCE_NAME_PREFIX ,
29+ testName : `Decorator${ outputFormat } ` ,
12030 } ,
12131 } ) ;
12232
123- // Check the other custom subsegment and its subsegments
124- expect ( subsegments . has ( '### methodNoResponse' ) ) . toBe ( true ) ;
125- expect ( subsegments . get ( '### methodNoResponse' ) ?. metadata ) . toBeUndefined ( ) ;
126- expect ( subsegments . get ( '### methodNoResponse' ) ?. subsegments ?. length ) . toBe (
127- 1
33+ // Location of the lambda function code
34+ const lambdaFunctionCodeFilePath = join (
35+ __dirname ,
36+ 'decorator.test.functionCode.ts'
12837 ) ;
129- expect (
130- subsegments . get ( '### methodNoResponse' ) ?. subsegments ?. [ 0 ] ?. name ===
131- 'DynamoDB'
132- ) . toBe ( true ) ;
133-
134- // Check the annotations of the main segment
135- if ( ! annotations ) {
136- throw new Error ( 'No annotations found on the main segment' ) ;
137- }
138- expect ( annotations . ColdStart ) . toEqual ( true ) ;
139- expect ( annotations . Service ) . toEqual ( 'Decorator' ) ;
140- expect ( annotations [ expectedCustomAnnotationKey ] ) . toEqual (
141- expectedCustomAnnotationValue
38+ const startTime = new Date ( ) ;
39+
40+ const testTable = new TestDynamodbTable (
41+ testStack ,
42+ { } ,
43+ {
44+ nameSuffix : 'TestTable' ,
45+ }
14246 ) ;
14347
144- // Check the metadata of the main segment
145- if ( ! metadata ) {
146- throw new Error ( 'No metadata found on the main segment' ) ;
147- }
148- expect ( metadata . Decorator [ expectedCustomMetadataKey ] ) . toEqual (
149- expectedCustomMetadataValue
48+ const fnDecorator = new TestNodejsFunction (
49+ testStack ,
50+ {
51+ entry : lambdaFunctionCodeFilePath ,
52+ environment : {
53+ TEST_TABLE_NAME : testTable . tableName ,
54+ POWERTOOLS_SERVICE_NAME : 'Decorator' ,
55+ } ,
56+ } ,
57+ {
58+ nameSuffix : 'Decorator' ,
59+ outputFormat,
60+ shouldPolyfillRequire : outputFormat === 'ESM' ,
61+ }
15062 ) ;
63+ testTable . grantWriteData ( fnDecorator ) ;
64+
65+ const invocationCount = 2 ;
66+ let traceData : EnrichedXRayTraceDocumentParsed [ ] = [ ] ;
67+
68+ beforeAll ( async ( ) => {
69+ // Deploy the stack
70+ await testStack . deploy ( ) ;
71+
72+ // Get the actual function names from the stack outputs
73+ const fnNameDecorator = testStack . findAndGetStackOutputValue ( 'Decorator' ) ;
74+
75+ // Act
76+ await invokeAllTestCases ( fnNameDecorator , invocationCount ) ;
77+ traceData = await getTraces ( {
78+ startTime,
79+ resourceName : fnNameDecorator ,
80+ expectedTracesCount : invocationCount ,
81+ /**
82+ * The trace should have 4 segments:
83+ * 1. Lambda Context (AWS::Lambda)
84+ * 2. Lambda Function (AWS::Lambda::Function)
85+ * 4. DynamoDB (AWS::DynamoDB)
86+ * 4. Remote call (docs.aws.amazon.com)
87+ */
88+ expectedSegmentsCount : 4 ,
89+ } ) ;
90+ } ) ;
15191
152- // Check the response is present in the metadata
153- expect ( metadata . Decorator [ 'index.handler response' ] ) . toEqual (
154- expectedCustomResponseValue
155- ) ;
156- } ) ;
157-
158- it ( 'should annotate the trace with error data correctly' , ( ) => {
159- const mainSubsegment = traceData [ 1 ] ;
160- const { annotations } = mainSubsegment ;
161-
162- // Check the annotations of the main segment
163- if ( ! annotations ) {
164- throw new Error ( 'No annotations found on the main segment' ) ;
165- }
166- expect ( annotations . ColdStart ) . toEqual ( false ) ;
167-
168- // Check that the main segment has error data
169- expect ( mainSubsegment . fault ) . toBe ( true ) ;
170- expect ( Object . hasOwn ( mainSubsegment , 'cause' ) ) . toBe ( true ) ;
171- expect ( mainSubsegment . cause ?. exceptions [ 0 ] . message ) . toBe (
172- expectedCustomErrorMessage
173- ) ;
174- } ) ;
175- } ) ;
92+ afterAll ( async ( ) => {
93+ if ( ! process . env . DISABLE_TEARDOWN ) {
94+ await testStack . destroy ( ) ;
95+ }
96+ } ) ;
97+
98+ it ( 'should generate all trace data correctly' , ( ) => {
99+ // Assess
100+ const mainSubsegment = traceData [ 0 ] ;
101+ const { subsegments, annotations, metadata } = mainSubsegment ;
102+
103+ // Check the main segment name
104+ expect ( mainSubsegment . name ) . toBe ( '## index.handler' ) ;
105+
106+ // Check the subsegments of the main segment
107+ expect ( subsegments . size ) . toBe ( 3 ) ;
108+
109+ // Check remote call subsegment
110+ expect ( subsegments . has ( 'docs.aws.amazon.com' ) ) . toBe ( true ) ;
111+ const httpSubsegment = subsegments . get ( 'docs.aws.amazon.com' ) ;
112+ expect ( httpSubsegment ?. namespace ) . toBe ( 'remote' ) ;
113+ expect ( httpSubsegment ?. http ?. request ?. url ) . toEqual (
114+ 'https://docs.aws.amazon.com/powertools/typescript/latest/'
115+ ) ;
116+ expect ( httpSubsegment ?. http ?. request ?. method ) . toBe ( 'GET' ) ;
117+ expect ( httpSubsegment ?. http ?. response ?. status ) . toEqual (
118+ expect . any ( Number )
119+ ) ;
120+ expect ( httpSubsegment ?. http ?. response ?. status ) . toEqual (
121+ expect . any ( Number )
122+ ) ;
123+
124+ // Check the custom subsegment name & metadata
125+ expect ( subsegments . has ( expectedCustomSubSegmentName ) ) . toBe ( true ) ;
126+ expect (
127+ subsegments . get ( expectedCustomSubSegmentName ) ?. metadata
128+ ) . toStrictEqual ( {
129+ Decorator : {
130+ 'myMethod response' : expectedCustomResponseValue ,
131+ } ,
132+ } ) ;
133+
134+ // Check the other custom subsegment and its subsegments
135+ expect ( subsegments . has ( '### methodNoResponse' ) ) . toBe ( true ) ;
136+ expect ( subsegments . get ( '### methodNoResponse' ) ?. metadata ) . toBeUndefined ( ) ;
137+ expect ( subsegments . get ( '### methodNoResponse' ) ?. subsegments ?. length ) . toBe (
138+ 1
139+ ) ;
140+ expect (
141+ subsegments . get ( '### methodNoResponse' ) ?. subsegments ?. [ 0 ] ?. name ===
142+ 'DynamoDB'
143+ ) . toBe ( true ) ;
144+
145+ // Check the annotations of the main segment
146+ if ( ! annotations ) {
147+ throw new Error ( 'No annotations found on the main segment' ) ;
148+ }
149+ expect ( annotations . ColdStart ) . toEqual ( true ) ;
150+ expect ( annotations . Service ) . toEqual ( 'Decorator' ) ;
151+ expect ( annotations [ expectedCustomAnnotationKey ] ) . toEqual (
152+ expectedCustomAnnotationValue
153+ ) ;
154+
155+ // Check the metadata of the main segment
156+ if ( ! metadata ) {
157+ throw new Error ( 'No metadata found on the main segment' ) ;
158+ }
159+ expect ( metadata . Decorator [ expectedCustomMetadataKey ] ) . toEqual (
160+ expectedCustomMetadataValue
161+ ) ;
162+
163+ // Check the response is present in the metadata
164+ expect ( metadata . Decorator [ 'index.handler response' ] ) . toEqual (
165+ expectedCustomResponseValue
166+ ) ;
167+ } ) ;
168+
169+ it ( 'should annotate the trace with error data correctly' , ( ) => {
170+ const mainSubsegment = traceData [ 1 ] ;
171+ const { annotations } = mainSubsegment ;
172+
173+ // Check the annotations of the main segment
174+ if ( ! annotations ) {
175+ throw new Error ( 'No annotations found on the main segment' ) ;
176+ }
177+ expect ( annotations . ColdStart ) . toEqual ( false ) ;
178+
179+ // Check that the main segment has error data
180+ expect ( mainSubsegment . fault ) . toBe ( true ) ;
181+ expect ( Object . hasOwn ( mainSubsegment , 'cause' ) ) . toBe ( true ) ;
182+ expect ( mainSubsegment . cause ?. exceptions [ 0 ] . message ) . toBe (
183+ expectedCustomErrorMessage
184+ ) ;
185+ } ) ;
186+ }
187+ ) ;
0 commit comments