2
2
// SPDX-License-Identifier: MIT-0
3
3
4
4
/**
5
- * Test metrics decorator
5
+ * Test metrics standard functions
6
6
*
7
- * @group e2e/metrics/decorator
7
+ * @group e2e/metrics/standardFunctions
8
8
*/
9
9
10
10
import { randomUUID } from 'crypto' ;
@@ -19,43 +19,44 @@ const cloudwatchClient = new AWS.CloudWatch();
19
19
const lambdaClient = new AWS . Lambda ( ) ;
20
20
21
21
const integTestApp = new App ( ) ;
22
- const stack = new Stack ( integTestApp , 'ExampleIntegTest ' ) ;
22
+ const stack = new Stack ( integTestApp , 'MetricsE2EStandardFunctionsStack ' ) ;
23
23
24
- describe ( 'coldstart' , ( ) => {
25
- it ( 'can be deploy succcessfully' , async ( ) => {
26
- // GIVEN
27
- const startTime = new Date ( ) ;
28
- const expectedNamespace = randomUUID ( ) ; // to easily find metrics back at assert phase
29
- const expectedServiceName = 'MyFunctionWithStandardHandler' ;
30
- const expectedMetricName = 'MyMetric' ;
31
- const expectedMetricUnit = MetricUnits . Count ;
32
- const expectedMetricValue = '1' ;
33
- const expectedDefaultDimensions = { MyDimension : 'MyValue' } ;
34
- const expectedExtraDimension = { MyExtraDimension : 'MyExtraValue' } ;
35
- const expectedSingleMetricDimension = { MySingleMetricDim : 'MySingleValue' } ;
36
- const expectedSingleMetricName = 'MySingleMetric' ;
37
- const expectedSingleMetricUnit = MetricUnits . Percent ;
38
- const expectedSingleMetricValue = '2' ;
39
- const functionName = 'MyFunctionWithStandardHandler' ;
40
- new lambda . NodejsFunction ( stack , 'MyFunction' , {
41
- functionName : functionName ,
42
- environment : {
43
- EXPECTED_NAMESPACE : expectedNamespace ,
44
- EXPECTED_SERVICE_NAME : expectedServiceName ,
45
- EXPECTED_METRIC_NAME : expectedMetricName ,
46
- EXPECTED_METRIC_UNIT : expectedMetricUnit ,
47
- EXPECTED_METRIC_VALUE : expectedMetricValue ,
48
- EXPECTED_DEFAULT_DIMENSIONS : JSON . stringify ( expectedDefaultDimensions ) ,
49
- EXPECTED_EXTRA_DIMENSION : JSON . stringify ( expectedExtraDimension ) ,
50
- EXPECTED_SINGLE_METRIC_DIMENSION : JSON . stringify ( expectedSingleMetricDimension ) ,
51
- EXPECTED_SINGLE_METRIC_NAME : expectedSingleMetricName ,
52
- EXPECTED_SINGLE_METRIC_UNIT : expectedSingleMetricUnit ,
53
- EXPECTED_SINGLE_METRIC_VALUE : expectedSingleMetricValue ,
54
- } ,
55
- } ) ;
24
+ // GIVEN
25
+ const startTime = new Date ( ) ;
26
+ const expectedNamespace = randomUUID ( ) ; // to easily find metrics back at assert phase
27
+ const expectedServiceName = 'MyFunctionWithStandardHandler' ;
28
+ const expectedMetricName = 'MyMetric' ;
29
+ const expectedMetricUnit = MetricUnits . Count ;
30
+ const expectedMetricValue = '1' ;
31
+ const expectedDefaultDimensions = { MyDimension : 'MyValue' } ;
32
+ const expectedExtraDimension = { MyExtraDimension : 'MyExtraValue' } ;
33
+ const expectedSingleMetricDimension = { MySingleMetricDim : 'MySingleValue' } ;
34
+ const expectedSingleMetricName = 'MySingleMetric' ;
35
+ const expectedSingleMetricUnit = MetricUnits . Percent ;
36
+ const expectedSingleMetricValue = '2' ;
37
+ const functionName = 'MyFunctionWithStandardHandler' ;
38
+ new lambda . NodejsFunction ( stack , 'MyFunction' , {
39
+ functionName : functionName ,
40
+ tracing : Tracing . ACTIVE ,
41
+ environment : {
42
+ EXPECTED_NAMESPACE : expectedNamespace ,
43
+ EXPECTED_SERVICE_NAME : expectedServiceName ,
44
+ EXPECTED_METRIC_NAME : expectedMetricName ,
45
+ EXPECTED_METRIC_UNIT : expectedMetricUnit ,
46
+ EXPECTED_METRIC_VALUE : expectedMetricValue ,
47
+ EXPECTED_DEFAULT_DIMENSIONS : JSON . stringify ( expectedDefaultDimensions ) ,
48
+ EXPECTED_EXTRA_DIMENSION : JSON . stringify ( expectedExtraDimension ) ,
49
+ EXPECTED_SINGLE_METRIC_DIMENSION : JSON . stringify ( expectedSingleMetricDimension ) ,
50
+ EXPECTED_SINGLE_METRIC_NAME : expectedSingleMetricName ,
51
+ EXPECTED_SINGLE_METRIC_UNIT : expectedSingleMetricUnit ,
52
+ EXPECTED_SINGLE_METRIC_VALUE : expectedSingleMetricValue ,
53
+ } ,
54
+ } ) ;
56
55
57
- const stackArtifact = integTestApp . synth ( ) . getStackByName ( stack . stackName ) ;
56
+ const stackArtifact = integTestApp . synth ( ) . getStackByName ( stack . stackName ) ;
58
57
58
+ describe ( 'happy cases' , ( ) => {
59
+ beforeAll ( async ( ) => {
59
60
const sdkProvider = await SdkProvider . withAwsCliCompatibleDefaults ( {
60
61
profile : process . env . AWS_PROFILE ,
61
62
} ) ;
@@ -66,7 +67,11 @@ describe('coldstart', () => {
66
67
await cloudFormation . deployStack ( {
67
68
stack : stackArtifact ,
68
69
} ) ;
69
- // and invoked
70
+ } , 200000 ) ;
71
+
72
+ it ( 'capture ColdStart Metric' , async ( ) => {
73
+ // WHEN
74
+ // invoked
70
75
await lambdaClient
71
76
. invoke ( {
72
77
FunctionName : functionName ,
@@ -106,27 +111,82 @@ describe('coldstart', () => {
106
111
MetricName : 'ColdStart' ,
107
112
Statistics : [ 'Sum' ] ,
108
113
} ,
109
- undefined ,
114
+ undefined
110
115
)
111
116
. promise ( ) ;
112
117
113
118
// Despite lambda has been called twice, coldstart metric sum should only be 1
114
119
const singleDataPoint = coldStartMetricStat . Datapoints ? coldStartMetricStat . Datapoints [ 0 ] : { } ;
115
120
expect ( singleDataPoint . Sum ) . toBe ( 1 ) ;
116
- } , 9000000 ) ;
117
- } ) ;
121
+ } , 15000 ) ;
118
122
119
- afterAll ( async ( ) => {
120
- if ( ! process . env . DISABLE_TEARDOWN ) {
121
- const stackArtifact = integTestApp . synth ( ) . getStackByName ( stack . stackName ) ;
123
+ it ( 'produce added Metric with the default and extra one dimensions' , async ( ) => {
124
+ // GIVEN
125
+ const invocationCount = 2 ;
122
126
123
- const sdkProvider = await SdkProvider . withAwsCliCompatibleDefaults ( {
124
- profile : process . env . AWS_PROFILE ,
125
- } ) ;
126
- const cloudFormation = new CloudFormationDeployments ( { sdkProvider } ) ;
127
+ // WHEN
128
+ // invoked
129
+ for ( let i = 0 ; i < invocationCount ; i ++ ) {
130
+ await lambdaClient
131
+ . invoke ( {
132
+ FunctionName : functionName ,
133
+ } )
134
+ . promise ( ) ;
135
+ }
127
136
128
- await cloudFormation . destroyStack ( {
129
- stack : stackArtifact ,
130
- } ) ;
131
- }
132
- } , 9000000 ) ;
137
+ // THEN
138
+ // sleep to allow metrics to be collected
139
+ await new Promise ( ( resolve ) => setTimeout ( resolve , 10000 ) ) ;
140
+
141
+ // Check metric dimensions
142
+ const metrics = await cloudwatchClient
143
+ . listMetrics ( {
144
+ Namespace : expectedNamespace ,
145
+ MetricName : expectedMetricName ,
146
+ } )
147
+ . promise ( ) ;
148
+ expect ( metrics . Metrics ?. length ) . toBe ( 1 ) ;
149
+ const metric = metrics . Metrics ?. [ 0 ] ;
150
+ const expectedDimensions = [
151
+ { Name : 'service' , Value : expectedServiceName } ,
152
+ { Name : Object . keys ( expectedDefaultDimensions ) [ 0 ] , Value : expectedDefaultDimensions . MyDimension } ,
153
+ { Name : Object . keys ( expectedExtraDimension ) [ 0 ] , Value : expectedExtraDimension . MyExtraDimension } ,
154
+ ] ;
155
+ expect ( metric ?. Dimensions ) . toStrictEqual ( expectedDimensions ) ;
156
+
157
+ // Check coldstart metric value
158
+ const metricStat = await cloudwatchClient
159
+ . getMetricStatistics (
160
+ {
161
+ Namespace : expectedNamespace ,
162
+ StartTime : new Date ( startTime . getTime ( ) - 60 * 1000 ) , // minus 1 minute,
163
+ Dimensions : expectedDimensions ,
164
+ EndTime : new Date ( new Date ( ) . getTime ( ) + 60 * 1000 ) ,
165
+ Period : 60 ,
166
+ MetricName : expectedMetricName ,
167
+ Statistics : [ 'Sum' ] ,
168
+ } ,
169
+ undefined
170
+ )
171
+ . promise ( ) ;
172
+
173
+ // Since lambda has been called twice in this test and potentially more in others, metric sum should be at least of expectedMetricValue * invocationCount
174
+ const singleDataPoint = metricStat . Datapoints ? metricStat . Datapoints [ 0 ] : { } ;
175
+ expect ( singleDataPoint . Sum ) . toBeGreaterThanOrEqual ( parseInt ( expectedMetricValue ) * invocationCount ) ;
176
+ } , 15000 ) ;
177
+
178
+ afterAll ( async ( ) => {
179
+ if ( ! process . env . DISABLE_TEARDOWN ) {
180
+ const stackArtifact = integTestApp . synth ( ) . getStackByName ( stack . stackName ) ;
181
+
182
+ const sdkProvider = await SdkProvider . withAwsCliCompatibleDefaults ( {
183
+ profile : process . env . AWS_PROFILE ,
184
+ } ) ;
185
+ const cloudFormation = new CloudFormationDeployments ( { sdkProvider } ) ;
186
+
187
+ await cloudFormation . destroyStack ( {
188
+ stack : stackArtifact ,
189
+ } ) ;
190
+ }
191
+ } , 200000 ) ;
192
+ } ) ;
0 commit comments