From 72e3de1ce1e993ad452a3412901bec01d648a8b7 Mon Sep 17 00:00:00 2001 From: Collin Dillinger Date: Fri, 23 May 2025 22:12:03 -0400 Subject: [PATCH 1/3] feat(cloudwatch-dashboards): add support for queryLanguage property --- .../aws-cdk-cloudwatch-alarms.assets.json | 7 +- .../aws-cdk-cloudwatch-alarms.template.json | 12 +- .../cdk.out | 2 +- ...efaultTestDeployAssertD2D0B407.assets.json | 3 +- .../integ.json | 5 +- .../manifest.json | 228 ++++++++++++++- .../tree.json | 266 +----------------- .../test/integ.alarm-and-dashboard.ts | 7 + .../aws-cloudwatch/lib/log-query.ts | 17 +- .../aws-cloudwatch/test/graphs.test.ts | 28 ++ 10 files changed, 293 insertions(+), 282 deletions(-) diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/aws-cdk-cloudwatch-alarms.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/aws-cdk-cloudwatch-alarms.assets.json index 77c985c557eb7..4dbb660a71753 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/aws-cdk-cloudwatch-alarms.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/aws-cdk-cloudwatch-alarms.assets.json @@ -1,7 +1,8 @@ { - "version": "30.0.0", + "version": "41.0.0", "files": { - "8b034d9d120c7cc38051e76b8ef13c8d1d39695afe0a5a779edce36ae5596486": { + "9bfbf7e2084723f490ac482e7794c9a980b37a03901abbab84283d7bbd45baf9": { + "displayName": "aws-cdk-cloudwatch-alarms Template", "source": { "path": "aws-cdk-cloudwatch-alarms.template.json", "packaging": "file" @@ -9,7 +10,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "8b034d9d120c7cc38051e76b8ef13c8d1d39695afe0a5a779edce36ae5596486.json", + "objectKey": "9bfbf7e2084723f490ac482e7794c9a980b37a03901abbab84283d7bbd45baf9.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/aws-cdk-cloudwatch-alarms.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/aws-cdk-cloudwatch-alarms.template.json index 840bdd623139e..9291adb4a1b7e 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/aws-cdk-cloudwatch-alarms.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/aws-cdk-cloudwatch-alarms.template.json @@ -7,7 +7,6 @@ "Type": "AWS::CloudWatch::Alarm", "Properties": { "ComparisonOperator": "GreaterThanOrEqualToThreshold", - "EvaluationPeriods": 3, "DatapointsToAlarm": 2, "Dimensions": [ { @@ -20,6 +19,7 @@ } } ], + "EvaluationPeriods": 3, "MetricName": "ApproximateNumberOfMessagesVisible", "Namespace": "AWS/SQS", "Period": 300, @@ -94,7 +94,11 @@ { "Ref": "AWS::Region" }, - "\",\"query\":\"SOURCE 'my-log-group' | fields @message\\n | filter @message like /Error/\"}},{\"type\":\"metric\",\"width\":6,\"height\":3,\"x\":0,\"y\":50,\"properties\":{\"view\":\"singleValue\",\"title\":\"Sent message size\",\"region\":\"", + "\",\"query\":\"SOURCE 'my-log-group' | fields @message\\n | filter @message like /Error/\"}},{\"type\":\"log\",\"width\":6,\"height\":6,\"x\":0,\"y\":50,\"properties\":{\"view\":\"pie\",\"title\":\"Errors in my log group - pie\",\"region\":\"", + { + "Ref": "AWS::Region" + }, + "\",\"query\":\"SOURCE 'my-log-group' | SELECT count(*) as count FROM 'my-log-group'\",\"queryLanguage\":\"SQL\"}},{\"type\":\"metric\",\"width\":6,\"height\":3,\"x\":0,\"y\":56,\"properties\":{\"view\":\"singleValue\",\"title\":\"Sent message size\",\"region\":\"", { "Ref": "AWS::Region" }, @@ -105,7 +109,7 @@ "QueueName" ] }, - "\"]],\"singleValueFullPrecision\":false}},{\"type\":\"metric\",\"width\":6,\"height\":3,\"x\":0,\"y\":53,\"properties\":{\"view\":\"singleValue\",\"title\":\"Sent message size with full precision\",\"region\":\"", + "\"]],\"singleValueFullPrecision\":false}},{\"type\":\"metric\",\"width\":6,\"height\":3,\"x\":0,\"y\":59,\"properties\":{\"view\":\"singleValue\",\"title\":\"Sent message size with full precision\",\"region\":\"", { "Ref": "AWS::Region" }, @@ -116,7 +120,7 @@ "QueueName" ] }, - "\"]],\"singleValueFullPrecision\":true}},{\"type\":\"custom\",\"width\":6,\"height\":6,\"x\":0,\"y\":56,\"properties\":{\"endpoint\":\"arn:aws:lambda:us-west-2:123456789012:function:my-function\",\"title\":\"My custom alarm\",\"updateOn\":{\"refresh\":true,\"resize\":true,\"timeRange\":true}}}]}" + "\"]],\"singleValueFullPrecision\":true}},{\"type\":\"custom\",\"width\":6,\"height\":6,\"x\":0,\"y\":62,\"properties\":{\"endpoint\":\"arn:aws:lambda:us-west-2:123456789012:function:my-function\",\"title\":\"My custom alarm\",\"updateOn\":{\"refresh\":true,\"resize\":true,\"timeRange\":true}}}]}" ] ] }, diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/cdk.out index ae4b03c54e770..188478b55560e 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/cdk.out +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"30.0.0"} \ No newline at end of file +{"version":"41.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/cdkcloudwatchalarmsintegtestDefaultTestDeployAssertD2D0B407.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/cdkcloudwatchalarmsintegtestDefaultTestDeployAssertD2D0B407.assets.json index eb5c6208f5d8a..9e761a3667a03 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/cdkcloudwatchalarmsintegtestDefaultTestDeployAssertD2D0B407.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/cdkcloudwatchalarmsintegtestDefaultTestDeployAssertD2D0B407.assets.json @@ -1,7 +1,8 @@ { - "version": "30.0.0", + "version": "41.0.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "displayName": "cdkcloudwatchalarmsintegtestDefaultTestDeployAssertD2D0B407 Template", "source": { "path": "cdkcloudwatchalarmsintegtestDefaultTestDeployAssertD2D0B407.template.json", "packaging": "file" diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/integ.json index 5490a0f0533fd..36ff0bc448f68 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "41.0.0", "testCases": { "cdk-cloudwatch-alarms-integ-test/DefaultTest": { "stacks": [ @@ -8,5 +8,6 @@ "assertionStack": "cdk-cloudwatch-alarms-integ-test/DefaultTest/DeployAssert", "assertionStackName": "cdkcloudwatchalarmsintegtestDefaultTestDeployAssertD2D0B407" } - } + }, + "minimumCliVersion": "2.1005.0" } \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/manifest.json index 36f062e02ebbd..4f85efc270f31 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "30.0.0", + "version": "43.0.0", "artifacts": { "aws-cdk-cloudwatch-alarms.assets": { "type": "cdk:asset-manifest", @@ -14,10 +14,11 @@ "environment": "aws://unknown-account/unknown-region", "properties": { "templateFile": "aws-cdk-cloudwatch-alarms.template.json", + "terminationProtection": false, "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/8b034d9d120c7cc38051e76b8ef13c8d1d39695afe0a5a779edce36ae5596486.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/9bfbf7e2084723f490ac482e7794c9a980b37a03901abbab84283d7bbd45baf9.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -39,12 +40,231 @@ "data": "queue" } ], + "/aws-cdk-cloudwatch-alarms/Alarm": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "metric": { + "warnings": "*" + }, + "alarmName": "*", + "alarmDescription": "*", + "comparisonOperator": "*", + "datapointsToAlarm": "*", + "threshold": "*", + "evaluationPeriods": "*", + "evaluateLowSampleCountPercentile": "*", + "treatMissingData": "*", + "actionsEnabled": "*" + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "toAnnotation": [] + } + } + ], "/aws-cdk-cloudwatch-alarms/Alarm/Resource": [ { "type": "aws:cdk:logicalId", "data": "Alarm7103F465" } ], + "/aws-cdk-cloudwatch-alarms/Dash": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "dashboardName": "*", + "start": "*", + "end": "*", + "periodOverride": "inherit" + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addWidgets": [ + { + "warnings": "*", + "warningsV2": "*", + "width": "*", + "height": "*" + }, + "*" + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addWidgets": [ + { + "warnings": "*", + "warningsV2": "*", + "width": "*", + "height": "*" + } + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addWidgets": [ + { + "warnings": "*", + "warningsV2": "*", + "width": "*", + "height": "*" + } + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addWidgets": [ + { + "warnings": "*", + "warningsV2": "*", + "width": "*", + "height": "*" + } + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addWidgets": [ + { + "warnings": "*", + "warningsV2": "*", + "width": "*", + "height": "*" + } + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addWidgets": [ + { + "warnings": "*", + "warningsV2": "*", + "width": "*", + "height": "*" + } + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addWidgets": [ + { + "warnings": "*", + "warningsV2": "*", + "width": "*", + "height": "*" + } + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addWidgets": [ + { + "warnings": "*", + "warningsV2": "*", + "width": "*", + "height": "*" + } + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addWidgets": [ + { + "warnings": "*", + "warningsV2": "*", + "width": "*", + "height": "*" + } + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addWidgets": [ + { + "warnings": "*", + "warningsV2": "*", + "width": "*", + "height": "*" + } + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addWidgets": [ + { + "warnings": "*", + "warningsV2": "*", + "width": "*", + "height": "*" + } + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addWidgets": [ + { + "warnings": "*", + "warningsV2": "*", + "width": "*", + "height": "*" + } + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addWidgets": [ + { + "warnings": "*", + "warningsV2": "*", + "width": "*", + "height": "*" + } + ] + } + }, + { + "type": "aws:cdk:analytics:method", + "data": { + "addWidgets": [ + { + "warnings": "*", + "warningsV2": "*", + "width": "*", + "height": "*" + } + ] + } + } + ], "/aws-cdk-cloudwatch-alarms/Dash/Resource": [ { "type": "aws:cdk:logicalId", @@ -79,6 +299,7 @@ "environment": "aws://unknown-account/unknown-region", "properties": { "templateFile": "cdkcloudwatchalarmsintegtestDefaultTestDeployAssertD2D0B407.template.json", + "terminationProtection": false, "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", @@ -119,5 +340,6 @@ "file": "tree.json" } } - } + }, + "minimumCliVersion": "2.1015.0" } \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/tree.json index 41d92ed3c6779..43f158d69c786 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.js.snapshot/tree.json @@ -1,265 +1 @@ -{ - "version": "tree-0.1", - "tree": { - "id": "App", - "path": "", - "children": { - "aws-cdk-cloudwatch-alarms": { - "id": "aws-cdk-cloudwatch-alarms", - "path": "aws-cdk-cloudwatch-alarms", - "children": { - "queue": { - "id": "queue", - "path": "aws-cdk-cloudwatch-alarms/queue", - "constructInfo": { - "fqn": "@aws-cdk/core.CfnResource", - "version": "0.0.0" - } - }, - "Alarm": { - "id": "Alarm", - "path": "aws-cdk-cloudwatch-alarms/Alarm", - "children": { - "Resource": { - "id": "Resource", - "path": "aws-cdk-cloudwatch-alarms/Alarm/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::CloudWatch::Alarm", - "aws:cdk:cloudformation:props": { - "comparisonOperator": "GreaterThanOrEqualToThreshold", - "evaluationPeriods": 3, - "datapointsToAlarm": 2, - "dimensions": [ - { - "name": "QueueName", - "value": { - "Fn::GetAtt": [ - "queue", - "QueueName" - ] - } - } - ], - "metricName": "ApproximateNumberOfMessagesVisible", - "namespace": "AWS/SQS", - "period": 300, - "statistic": "Average", - "threshold": 100 - } - }, - "constructInfo": { - "fqn": "@aws-cdk/aws-cloudwatch.CfnAlarm", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/aws-cloudwatch.Alarm", - "version": "0.0.0" - } - }, - "Dash": { - "id": "Dash", - "path": "aws-cdk-cloudwatch-alarms/Dash", - "children": { - "Resource": { - "id": "Resource", - "path": "aws-cdk-cloudwatch-alarms/Dash/Resource", - "attributes": { - "aws:cdk:cloudformation:type": "AWS::CloudWatch::Dashboard", - "aws:cdk:cloudformation:props": { - "dashboardBody": { - "Fn::Join": [ - "", - [ - "{\"start\":\"-9H\",\"end\":\"2018-12-17T06:00:00.000Z\",\"periodOverride\":\"inherit\",\"widgets\":[{\"type\":\"text\",\"width\":6,\"height\":2,\"x\":0,\"y\":0,\"properties\":{\"markdown\":\"# This is my dashboard\"}},{\"type\":\"text\",\"width\":6,\"height\":2,\"x\":6,\"y\":0,\"properties\":{\"markdown\":\"you like?\"}},{\"type\":\"metric\",\"width\":6,\"height\":6,\"x\":0,\"y\":2,\"properties\":{\"view\":\"timeSeries\",\"title\":\"Messages in queue\",\"region\":\"", - { - "Ref": "AWS::Region" - }, - "\",\"annotations\":{\"alarms\":[\"", - { - "Fn::GetAtt": [ - "Alarm7103F465", - "Arn" - ] - }, - "\"]},\"yAxis\":{}}},{\"type\":\"alarm\",\"width\":6,\"height\":3,\"x\":0,\"y\":8,\"properties\":{\"title\":\"Firing alarms\",\"alarms\":[\"", - { - "Fn::GetAtt": [ - "Alarm7103F465", - "Arn" - ] - }, - "\"]}},{\"type\":\"metric\",\"width\":6,\"height\":6,\"x\":0,\"y\":11,\"properties\":{\"view\":\"timeSeries\",\"title\":\"More messages in queue with alarm annotation\",\"region\":\"", - { - "Ref": "AWS::Region" - }, - "\",\"metrics\":[[\"AWS/SQS\",\"ApproximateNumberOfMessagesVisible\",\"QueueName\",\"", - { - "Fn::GetAtt": [ - "queue", - "QueueName" - ] - }, - "\"]],\"annotations\":{\"horizontal\":[{\"label\":\"ApproximateNumberOfMessagesVisible >= 100 for 2 datapoints within 15 minutes\",\"value\":100,\"yAxis\":\"left\"}]},\"yAxis\":{}}},{\"type\":\"metric\",\"width\":6,\"height\":3,\"x\":0,\"y\":17,\"properties\":{\"view\":\"singleValue\",\"title\":\"Current messages in queue\",\"region\":\"", - { - "Ref": "AWS::Region" - }, - "\",\"metrics\":[[\"AWS/SQS\",\"ApproximateNumberOfMessagesVisible\",\"QueueName\",\"", - { - "Fn::GetAtt": [ - "queue", - "QueueName" - ] - }, - "\"]]}},{\"type\":\"log\",\"width\":6,\"height\":6,\"x\":0,\"y\":20,\"properties\":{\"view\":\"table\",\"title\":\"Errors in my log group\",\"region\":\"", - { - "Ref": "AWS::Region" - }, - "\",\"query\":\"SOURCE 'my-log-group' | fields @message\\n | filter @message like /Error/\"}},{\"type\":\"log\",\"width\":6,\"height\":6,\"x\":0,\"y\":26,\"properties\":{\"view\":\"bar\",\"title\":\"Errors in my log group - bar\",\"region\":\"", - { - "Ref": "AWS::Region" - }, - "\",\"query\":\"SOURCE 'my-log-group' | fields @message\\n | filter @message like /Error/\"}},{\"type\":\"log\",\"width\":6,\"height\":6,\"x\":0,\"y\":32,\"properties\":{\"view\":\"timeSeries\",\"title\":\"Errors in my log group - line\",\"region\":\"", - { - "Ref": "AWS::Region" - }, - "\",\"query\":\"SOURCE 'my-log-group' | fields @message\\n | filter @message like /Error/\",\"stacked\":false}},{\"type\":\"log\",\"width\":6,\"height\":6,\"x\":0,\"y\":38,\"properties\":{\"view\":\"timeSeries\",\"title\":\"Errors in my log group - stacked\",\"region\":\"", - { - "Ref": "AWS::Region" - }, - "\",\"query\":\"SOURCE 'my-log-group' | fields @message\\n | filter @message like /Error/\",\"stacked\":true}},{\"type\":\"log\",\"width\":6,\"height\":6,\"x\":0,\"y\":44,\"properties\":{\"view\":\"pie\",\"title\":\"Errors in my log group - pie\",\"region\":\"", - { - "Ref": "AWS::Region" - }, - "\",\"query\":\"SOURCE 'my-log-group' | fields @message\\n | filter @message like /Error/\"}},{\"type\":\"metric\",\"width\":6,\"height\":3,\"x\":0,\"y\":50,\"properties\":{\"view\":\"singleValue\",\"title\":\"Sent message size\",\"region\":\"", - { - "Ref": "AWS::Region" - }, - "\",\"metrics\":[[\"AWS/SQS\",\"SentMessageSize\",\"QueueName\",\"", - { - "Fn::GetAtt": [ - "queue", - "QueueName" - ] - }, - "\"]],\"singleValueFullPrecision\":false}},{\"type\":\"metric\",\"width\":6,\"height\":3,\"x\":0,\"y\":53,\"properties\":{\"view\":\"singleValue\",\"title\":\"Sent message size with full precision\",\"region\":\"", - { - "Ref": "AWS::Region" - }, - "\",\"metrics\":[[\"AWS/SQS\",\"SentMessageSize\",\"QueueName\",\"", - { - "Fn::GetAtt": [ - "queue", - "QueueName" - ] - }, - "\"]],\"singleValueFullPrecision\":true}},{\"type\":\"custom\",\"width\":6,\"height\":6,\"x\":0,\"y\":56,\"properties\":{\"endpoint\":\"arn:aws:lambda:us-west-2:123456789012:function:my-function\",\"title\":\"My custom alarm\",\"updateOn\":{\"refresh\":true,\"resize\":true,\"timeRange\":true}}}]}" - ] - ] - }, - "dashboardName": "MyCustomDashboardName" - } - }, - "constructInfo": { - "fqn": "@aws-cdk/aws-cloudwatch.CfnDashboard", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/aws-cloudwatch.Dashboard", - "version": "0.0.0" - } - }, - "BootstrapVersion": { - "id": "BootstrapVersion", - "path": "aws-cdk-cloudwatch-alarms/BootstrapVersion", - "constructInfo": { - "fqn": "@aws-cdk/core.CfnParameter", - "version": "0.0.0" - } - }, - "CheckBootstrapVersion": { - "id": "CheckBootstrapVersion", - "path": "aws-cdk-cloudwatch-alarms/CheckBootstrapVersion", - "constructInfo": { - "fqn": "@aws-cdk/core.CfnRule", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/core.Stack", - "version": "0.0.0" - } - }, - "cdk-cloudwatch-alarms-integ-test": { - "id": "cdk-cloudwatch-alarms-integ-test", - "path": "cdk-cloudwatch-alarms-integ-test", - "children": { - "DefaultTest": { - "id": "DefaultTest", - "path": "cdk-cloudwatch-alarms-integ-test/DefaultTest", - "children": { - "Default": { - "id": "Default", - "path": "cdk-cloudwatch-alarms-integ-test/DefaultTest/Default", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.252" - } - }, - "DeployAssert": { - "id": "DeployAssert", - "path": "cdk-cloudwatch-alarms-integ-test/DefaultTest/DeployAssert", - "children": { - "BootstrapVersion": { - "id": "BootstrapVersion", - "path": "cdk-cloudwatch-alarms-integ-test/DefaultTest/DeployAssert/BootstrapVersion", - "constructInfo": { - "fqn": "@aws-cdk/core.CfnParameter", - "version": "0.0.0" - } - }, - "CheckBootstrapVersion": { - "id": "CheckBootstrapVersion", - "path": "cdk-cloudwatch-alarms-integ-test/DefaultTest/DeployAssert/CheckBootstrapVersion", - "constructInfo": { - "fqn": "@aws-cdk/core.CfnRule", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/core.Stack", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/integ-tests.IntegTestCase", - "version": "0.0.0" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/integ-tests.IntegTest", - "version": "0.0.0" - } - }, - "Tree": { - "id": "Tree", - "path": "Tree", - "constructInfo": { - "fqn": "constructs.Construct", - "version": "10.1.252" - } - } - }, - "constructInfo": { - "fqn": "@aws-cdk/core.App", - "version": "0.0.0" - } - } -} \ No newline at end of file +{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"aws-cdk-cloudwatch-alarms":{"id":"aws-cdk-cloudwatch-alarms","path":"aws-cdk-cloudwatch-alarms","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"queue":{"id":"queue","path":"aws-cdk-cloudwatch-alarms/queue","constructInfo":{"fqn":"aws-cdk-lib.CfnResource","version":"0.0.0"}},"Alarm":{"id":"Alarm","path":"aws-cdk-cloudwatch-alarms/Alarm","constructInfo":{"fqn":"aws-cdk-lib.aws_cloudwatch.Alarm","version":"0.0.0","metadata":[{"metric":{"warnings":"*"},"alarmName":"*","alarmDescription":"*","comparisonOperator":"*","datapointsToAlarm":"*","threshold":"*","evaluationPeriods":"*","evaluateLowSampleCountPercentile":"*","treatMissingData":"*","actionsEnabled":"*"},{"toAnnotation":[]}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-cloudwatch-alarms/Alarm/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_cloudwatch.CfnAlarm","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::CloudWatch::Alarm","aws:cdk:cloudformation:props":{"comparisonOperator":"GreaterThanOrEqualToThreshold","datapointsToAlarm":2,"dimensions":[{"name":"QueueName","value":{"Fn::GetAtt":["queue","QueueName"]}}],"evaluationPeriods":3,"metricName":"ApproximateNumberOfMessagesVisible","namespace":"AWS/SQS","period":300,"statistic":"Average","threshold":100}}}}},"Dash":{"id":"Dash","path":"aws-cdk-cloudwatch-alarms/Dash","constructInfo":{"fqn":"aws-cdk-lib.aws_cloudwatch.Dashboard","version":"0.0.0","metadata":[{"dashboardName":"*","start":"*","end":"*","periodOverride":"inherit"},{"addWidgets":[{"warnings":"*","warningsV2":"*","width":"*","height":"*"},"*"]},{"addWidgets":[{"warnings":"*","warningsV2":"*","width":"*","height":"*"}]},{"addWidgets":[{"warnings":"*","warningsV2":"*","width":"*","height":"*"}]},{"addWidgets":[{"warnings":"*","warningsV2":"*","width":"*","height":"*"}]},{"addWidgets":[{"warnings":"*","warningsV2":"*","width":"*","height":"*"}]},{"addWidgets":[{"warnings":"*","warningsV2":"*","width":"*","height":"*"}]},{"addWidgets":[{"warnings":"*","warningsV2":"*","width":"*","height":"*"}]},{"addWidgets":[{"warnings":"*","warningsV2":"*","width":"*","height":"*"}]},{"addWidgets":[{"warnings":"*","warningsV2":"*","width":"*","height":"*"}]},{"addWidgets":[{"warnings":"*","warningsV2":"*","width":"*","height":"*"}]},{"addWidgets":[{"warnings":"*","warningsV2":"*","width":"*","height":"*"}]},{"addWidgets":[{"warnings":"*","warningsV2":"*","width":"*","height":"*"}]},{"addWidgets":[{"warnings":"*","warningsV2":"*","width":"*","height":"*"}]},{"addWidgets":[{"warnings":"*","warningsV2":"*","width":"*","height":"*"}]}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-cloudwatch-alarms/Dash/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_cloudwatch.CfnDashboard","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::CloudWatch::Dashboard","aws:cdk:cloudformation:props":{"dashboardBody":{"Fn::Join":["",["{\"start\":\"-9H\",\"end\":\"2018-12-17T06:00:00.000Z\",\"periodOverride\":\"inherit\",\"widgets\":[{\"type\":\"text\",\"width\":6,\"height\":2,\"x\":0,\"y\":0,\"properties\":{\"markdown\":\"# This is my dashboard\"}},{\"type\":\"text\",\"width\":6,\"height\":2,\"x\":6,\"y\":0,\"properties\":{\"markdown\":\"you like?\"}},{\"type\":\"metric\",\"width\":6,\"height\":6,\"x\":0,\"y\":2,\"properties\":{\"view\":\"timeSeries\",\"title\":\"Messages in queue\",\"region\":\"",{"Ref":"AWS::Region"},"\",\"annotations\":{\"alarms\":[\"",{"Fn::GetAtt":["Alarm7103F465","Arn"]},"\"]},\"yAxis\":{}}},{\"type\":\"alarm\",\"width\":6,\"height\":3,\"x\":0,\"y\":8,\"properties\":{\"title\":\"Firing alarms\",\"alarms\":[\"",{"Fn::GetAtt":["Alarm7103F465","Arn"]},"\"]}},{\"type\":\"metric\",\"width\":6,\"height\":6,\"x\":0,\"y\":11,\"properties\":{\"view\":\"timeSeries\",\"title\":\"More messages in queue with alarm annotation\",\"region\":\"",{"Ref":"AWS::Region"},"\",\"metrics\":[[\"AWS/SQS\",\"ApproximateNumberOfMessagesVisible\",\"QueueName\",\"",{"Fn::GetAtt":["queue","QueueName"]},"\"]],\"annotations\":{\"horizontal\":[{\"label\":\"ApproximateNumberOfMessagesVisible >= 100 for 2 datapoints within 15 minutes\",\"value\":100,\"yAxis\":\"left\"}]},\"yAxis\":{}}},{\"type\":\"metric\",\"width\":6,\"height\":3,\"x\":0,\"y\":17,\"properties\":{\"view\":\"singleValue\",\"title\":\"Current messages in queue\",\"region\":\"",{"Ref":"AWS::Region"},"\",\"metrics\":[[\"AWS/SQS\",\"ApproximateNumberOfMessagesVisible\",\"QueueName\",\"",{"Fn::GetAtt":["queue","QueueName"]},"\"]]}},{\"type\":\"log\",\"width\":6,\"height\":6,\"x\":0,\"y\":20,\"properties\":{\"view\":\"table\",\"title\":\"Errors in my log group\",\"region\":\"",{"Ref":"AWS::Region"},"\",\"query\":\"SOURCE 'my-log-group' | fields @message\\n | filter @message like /Error/\"}},{\"type\":\"log\",\"width\":6,\"height\":6,\"x\":0,\"y\":26,\"properties\":{\"view\":\"bar\",\"title\":\"Errors in my log group - bar\",\"region\":\"",{"Ref":"AWS::Region"},"\",\"query\":\"SOURCE 'my-log-group' | fields @message\\n | filter @message like /Error/\"}},{\"type\":\"log\",\"width\":6,\"height\":6,\"x\":0,\"y\":32,\"properties\":{\"view\":\"timeSeries\",\"title\":\"Errors in my log group - line\",\"region\":\"",{"Ref":"AWS::Region"},"\",\"query\":\"SOURCE 'my-log-group' | fields @message\\n | filter @message like /Error/\",\"stacked\":false}},{\"type\":\"log\",\"width\":6,\"height\":6,\"x\":0,\"y\":38,\"properties\":{\"view\":\"timeSeries\",\"title\":\"Errors in my log group - stacked\",\"region\":\"",{"Ref":"AWS::Region"},"\",\"query\":\"SOURCE 'my-log-group' | fields @message\\n | filter @message like /Error/\",\"stacked\":true}},{\"type\":\"log\",\"width\":6,\"height\":6,\"x\":0,\"y\":44,\"properties\":{\"view\":\"pie\",\"title\":\"Errors in my log group - pie\",\"region\":\"",{"Ref":"AWS::Region"},"\",\"query\":\"SOURCE 'my-log-group' | fields @message\\n | filter @message like /Error/\"}},{\"type\":\"log\",\"width\":6,\"height\":6,\"x\":0,\"y\":50,\"properties\":{\"view\":\"pie\",\"title\":\"Errors in my log group - pie\",\"region\":\"",{"Ref":"AWS::Region"},"\",\"query\":\"SOURCE 'my-log-group' | SELECT count(*) as count FROM 'my-log-group'\",\"queryLanguage\":\"SQL\"}},{\"type\":\"metric\",\"width\":6,\"height\":3,\"x\":0,\"y\":56,\"properties\":{\"view\":\"singleValue\",\"title\":\"Sent message size\",\"region\":\"",{"Ref":"AWS::Region"},"\",\"metrics\":[[\"AWS/SQS\",\"SentMessageSize\",\"QueueName\",\"",{"Fn::GetAtt":["queue","QueueName"]},"\"]],\"singleValueFullPrecision\":false}},{\"type\":\"metric\",\"width\":6,\"height\":3,\"x\":0,\"y\":59,\"properties\":{\"view\":\"singleValue\",\"title\":\"Sent message size with full precision\",\"region\":\"",{"Ref":"AWS::Region"},"\",\"metrics\":[[\"AWS/SQS\",\"SentMessageSize\",\"QueueName\",\"",{"Fn::GetAtt":["queue","QueueName"]},"\"]],\"singleValueFullPrecision\":true}},{\"type\":\"custom\",\"width\":6,\"height\":6,\"x\":0,\"y\":62,\"properties\":{\"endpoint\":\"arn:aws:lambda:us-west-2:123456789012:function:my-function\",\"title\":\"My custom alarm\",\"updateOn\":{\"refresh\":true,\"resize\":true,\"timeRange\":true}}}]}"]]},"dashboardName":"MyCustomDashboardName"}}}}},"BootstrapVersion":{"id":"BootstrapVersion","path":"aws-cdk-cloudwatch-alarms/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"aws-cdk-cloudwatch-alarms/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"cdk-cloudwatch-alarms-integ-test":{"id":"cdk-cloudwatch-alarms-integ-test","path":"cdk-cloudwatch-alarms-integ-test","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"cdk-cloudwatch-alarms-integ-test/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"cdk-cloudwatch-alarms-integ-test/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}},"DeployAssert":{"id":"DeployAssert","path":"cdk-cloudwatch-alarms-integ-test/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"cdk-cloudwatch-alarms-integ-test/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"cdk-cloudwatch-alarms-integ-test/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}}}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}}}}} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.ts index d87824ecf37fd..548480f37a41a 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-cloudwatch/test/integ.alarm-and-dashboard.ts @@ -93,6 +93,13 @@ dashboard.addWidgets(new cloudwatch.LogQueryWidget({ queryString: `fields @message | filter @message like /Error/`, })); +dashboard.addWidgets(new cloudwatch.LogQueryWidget({ + title: 'Errors in my log group - pie', + view: cloudwatch.LogQueryVisualizationType.PIE, + logGroupNames: ['my-log-group'], + queryString: "SELECT count(*) as count FROM 'my-log-group'", + queryLanguage: 'SQL', +})); dashboard.addWidgets(new cloudwatch.SingleValueWidget({ title: 'Sent message size', metrics: [sentMessageSizeMetric], diff --git a/packages/aws-cdk-lib/aws-cloudwatch/lib/log-query.ts b/packages/aws-cdk-lib/aws-cloudwatch/lib/log-query.ts index e9b5075f4e604..23373b33219dd 100644 --- a/packages/aws-cdk-lib/aws-cloudwatch/lib/log-query.ts +++ b/packages/aws-cdk-lib/aws-cloudwatch/lib/log-query.ts @@ -62,6 +62,13 @@ export interface LogQueryWidgetProps { */ readonly queryLines?: string[]; + /** + * The query language to use for the query. + * Supported values include: 'Logs', 'SQL', 'PPL' + * @default - Logs Insights Query Language (default CloudWatch Logs query language) + */ + readonly queryLanguage?: string; + /** * The region the metrics of this widget should be taken from * @@ -109,7 +116,6 @@ export class LogQueryWidget extends ConcreteWidget { throw new cdk.UnscopedValidationError('Specify exactly one of \'queryString\' and \'queryLines\''); } } - public toJson(): any[] { const sources = this.props.logGroupNames.map(l => `SOURCE '${l}'`).join(' | '); const query = this.props.queryLines @@ -117,13 +123,18 @@ export class LogQueryWidget extends ConcreteWidget { : this.props.queryString; const properties: any = { - view: this.props.view? this.props.view : LogQueryVisualizationType.TABLE, + view: this.props.view ? this.props.view : LogQueryVisualizationType.TABLE, title: this.props.title, region: this.props.region || cdk.Aws.REGION, query: `${sources} | ${query}`, }; - // adding stacked property in case of LINE or STACKEDAREA + // Add queryLanguage property if specified + if (this.props.queryLanguage) { + properties.queryLanguage = this.props.queryLanguage; + } + + // Add stacked property in case of LINE or STACKEDAREA if (this.props.view === LogQueryVisualizationType.LINE || this.props.view === LogQueryVisualizationType.STACKEDAREA) { // assign the right native view value. both types share the same value properties.view = 'timeSeries', diff --git a/packages/aws-cdk-lib/aws-cloudwatch/test/graphs.test.ts b/packages/aws-cdk-lib/aws-cloudwatch/test/graphs.test.ts index 6814814f9a94e..24a237fcdeddc 100644 --- a/packages/aws-cdk-lib/aws-cloudwatch/test/graphs.test.ts +++ b/packages/aws-cdk-lib/aws-cloudwatch/test/graphs.test.ts @@ -313,6 +313,34 @@ describe('Graphs', () => { }]); }); + test('query result widget - sql', () => { + // GIVEN + const stack = new Stack(); + const logGroup = { logGroupName: 'my-log-group' }; + + // WHEN + const widget = new LogQueryWidget({ + logGroupNames: [logGroup.logGroupName], + view: LogQueryVisualizationType.STACKEDAREA, + queryString: "SELECT count(*) as count FROM 'my-log-group'", + queryLanguage: 'SQL', + }); + + // THEN + expect(stack.resolve(widget.toJson())).toEqual([{ + type: 'log', + width: 6, + height: 6, + properties: { + view: 'timeSeries', + stacked: true, + region: { Ref: 'AWS::Region' }, + query: "SOURCE 'my-log-group' | SELECT count(*) as count FROM 'my-log-group'", + queryLanguage: 'SQL', + }, + }]); + }); + test('alarm widget', () => { // GIVEN const stack = new Stack(); From d345941d2f6b789c5f5a3cfb5c1dc043c5674921 Mon Sep 17 00:00:00 2001 From: Collin Dillinger Date: Fri, 23 May 2025 23:22:38 -0400 Subject: [PATCH 2/3] Add README --- packages/aws-cdk-lib/aws-cloudwatch/README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/aws-cdk-lib/aws-cloudwatch/README.md b/packages/aws-cdk-lib/aws-cloudwatch/README.md index 415cb6d362ebb..395013744a9a6 100644 --- a/packages/aws-cdk-lib/aws-cloudwatch/README.md +++ b/packages/aws-cdk-lib/aws-cloudwatch/README.md @@ -790,6 +790,17 @@ dashboard.addWidgets(new cloudwatch.LogQueryWidget({ })); ``` +Log Insights QL is the default query language. You may specify an [alternate query language: OpenSearch PPL or SQL](https://aws.amazon.com/blogs/aws/new-amazon-cloudwatch-and-amazon-opensearch-service-launch-an-integrated-analytics-experience/), if desired: + +```ts +dashboard.addWidgets(new cloudwatch.LogQueryWidget({ + logGroupNames: ['my-log-group'], + view: cloudwatch.LogQueryVisualizationType.TABLE, + queryString: "SELECT count(*) as count FROM 'my-log-group'", + queryLanguage: 'SQL', +})); +``` + ### Custom widget A `CustomWidget` shows the result of an AWS Lambda function: From 1f194457d7d4da703d7328e99deb39f279d90909 Mon Sep 17 00:00:00 2001 From: Collin Dillinger Date: Thu, 5 Jun 2025 00:04:54 -0400 Subject: [PATCH 3/3] fix README code ref --- packages/aws-cdk-lib/aws-cloudwatch/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/aws-cdk-lib/aws-cloudwatch/README.md b/packages/aws-cdk-lib/aws-cloudwatch/README.md index 395013744a9a6..51aa50f6b0b60 100644 --- a/packages/aws-cdk-lib/aws-cloudwatch/README.md +++ b/packages/aws-cdk-lib/aws-cloudwatch/README.md @@ -793,6 +793,8 @@ dashboard.addWidgets(new cloudwatch.LogQueryWidget({ Log Insights QL is the default query language. You may specify an [alternate query language: OpenSearch PPL or SQL](https://aws.amazon.com/blogs/aws/new-amazon-cloudwatch-and-amazon-opensearch-service-launch-an-integrated-analytics-experience/), if desired: ```ts +declare const dashboard: cloudwatch.Dashboard; + dashboard.addWidgets(new cloudwatch.LogQueryWidget({ logGroupNames: ['my-log-group'], view: cloudwatch.LogQueryVisualizationType.TABLE,