Repository: cdklabs/cdk-monitoring-constructs (language: python)

Issue:
Lambda handlers should be upgraded to Node.js 18
### Version

v5.2.3

### Steps and/or minimal code example to reproduce

1. Use bitmap widgets or secrets monitoring

### Expected behavior

Have Lambda functions deployed that aren't using an EOL version of Node.js.

### Actual behavior

Functions are using Node.js 14.

### Other details

Relevant functions:
- https://github.com/cdklabs/cdk-monitoring-constructs/blob/81f0c6ba0211bca586c9b994ec7aa037b2cd6e3c/lib/dashboard/widget/BitmapWidget.ts#L37
- https://github.com/cdklabs/cdk-monitoring-constructs/blob/81f0c6ba0211bca586c9b994ec7aa037b2cd6e3c/lib/monitoring/aws-secretsmanager/SecretsManagerMetricsPublisher.ts#L37

The actual handlers need to be updated to use aws-sdk v3 and/or bundled code.


Discussion / hints:
> We are ending support for Node.js 14 in AWS Lambda. This follows Node.js 14 End-Of-Life (EOL) reached on April 30, 2023 [1].
>
> As described in the Lambda runtime support policy [2], end of support for language runtimes in Lambda happens in two stages. Starting November 27, 2023, Lambda will no longer apply security patches and other updates to the Node.js 14 runtime used by Lambda functions, and functions using Node.js 14 will no longer be eligible for technical support. In addition, you will no longer be able to create new Lambda functions using the Node.js 14 runtime. Starting January 25, 2024, you will no longer be able to update existing functions using the Node.js 14 runtime.
>
> We recommend that you upgrade your existing Node.js 14 functions to Node.js 18 before November 27, 2023.
>
> End of support does not impact function execution. Your functions will continue to run. However, they will be running on an unsupported runtime which is no longer maintained or patched by the AWS Lambda team.

Fix patch:
diff --git a/assets/BitmapWidgetRenderingSupport/index.js b/assets/BitmapWidgetRenderingSupport/index.js
index 8b8778f1..73d9f0ec 100644
--- a/assets/BitmapWidgetRenderingSupport/index.js
+++ b/assets/BitmapWidgetRenderingSupport/index.js
@@ -1,4 +1,4 @@
-const aws = require('aws-sdk');
+const { CloudWatchClient, GetMetricWidgetImageCommand } = require('@aws-sdk/client-cloudwatch');
 
 const DOCS = `
           ## Display a CloudWatch bitmap graph
@@ -21,27 +21,15 @@ const DOCS = `
 
 exports.handler = async (event) => {
     async function renderUsingCloudWatch(graph, width, height) {
-        const params = {MetricWidget: JSON.stringify(graph)};
-        const region = graph.region;
-        const customBackoff = (retryCount) => {
-            // Keep retrying with a random delay, long enough to overcome throttling from CW
-            const delay = 300 + Math.floor(Math.random() * 500);
-            console.log(`retry number ${retryCount} with a delay of ${delay} ms`);
-            return delay;
-        }
-        const clientOptions = {
-            region,
-            // Keep retrying until the Lambda times out
-            maxRetries: 99,
-            retryDelayOptions: {customBackoff},
-            httpOptions: {
-                connectTimeout: 3 * 1000,
-                timeout: 3 * 1000,
-            },
-        };
-        const cloudwatch = new aws.CloudWatch(clientOptions);
-        const image = await cloudwatch.getMetricWidgetImage(params).promise();
-        const base64Image = Buffer.from(image.MetricWidgetImage).toString('base64');
+        const client = new CloudWatchClient({
+            signingRegion: graph.region,
+            retryMode: 'standard',
+        });
+        const command = new GetMetricWidgetImageCommand({
+            MetricWidget: JSON.stringify(graph),
+        });
+        const response = await client.send(command);
+        const base64Image = Buffer.from(response.MetricWidgetImage).toString('base64');
         return `<img width="${width}" height="${height}" loading="lazy" src="data:image/png;base64,${base64Image}"/>`;
     }
 
diff --git a/lib/dashboard/widget/BitmapWidget.ts b/lib/dashboard/widget/BitmapWidget.ts
index bfc4f65d..7cfbcd26 100644
--- a/lib/dashboard/widget/BitmapWidget.ts
+++ b/lib/dashboard/widget/BitmapWidget.ts
@@ -34,7 +34,7 @@ export class BitmapWidgetRenderingSupport extends Construct {
         "Custom Widget Render for Bitmap Widgets (MonitoringCDKConstructs)",
       handler: "index.handler",
       memorySize: 128,
-      runtime: Runtime.NODEJS_14_X,
+      runtime: Runtime.NODEJS_18_X,
       timeout: Duration.seconds(60),
       logRetention: RetentionDays.ONE_DAY,
     });


Test patch:
diff --git a/test/dashboard/widget/__snapshots__/BitmapWidget.test.ts.snap b/test/dashboard/widget/__snapshots__/BitmapWidget.test.ts.snap
index abba281d..5d9aac16 100644
--- a/test/dashboard/widget/__snapshots__/BitmapWidget.test.ts.snap
+++ b/test/dashboard/widget/__snapshots__/BitmapWidget.test.ts.snap
@@ -109,7 +109,7 @@ Object {
             "Arn",
           ],
         },
-        "Runtime": "nodejs14.x",
+        "Runtime": "nodejs18.x",
         "Tags": Array [
           Object {
             "Key": "cw-custom-widget",