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

Issue:
add addMaxIncomingLogsAlarm to monitorLog
### Feature scope

cloudwatch

### Describe your suggested feature

in aws lambda there are cases where its preferred to console.error, but continue the execution, instead of raising an exception.

For this case I'd like to monitor logs, with a pattern and something like `addMaxIncomingLogsAlarm`

```ts
			.monitorLog({
				logGroupName: ...,
				pattern: "ERROR",
				alarmFriendlyName: "Handled exception occurred",
				addMaxIncomingLogsAlarm: {...},
			})
```


Discussion / hints:

Fix patch:
diff --git a/API.md b/API.md
index f8f581c3..5c7630a7 100644
--- a/API.md
+++ b/API.md
@@ -25206,6 +25206,7 @@ const logMonitoringProps: LogMonitoringProps = { ... }
 | <code><a href="#cdk-monitoring-constructs.LogMonitoringProps.property.addToSummaryDashboard">addToSummaryDashboard</a></code> | <code>boolean</code> | Flag indicating if the widgets should be added to summary dashboard. |
 | <code><a href="#cdk-monitoring-constructs.LogMonitoringProps.property.useCreatedAlarms">useCreatedAlarms</a></code> | <code><a href="#cdk-monitoring-constructs.IAlarmConsumer">IAlarmConsumer</a></code> | Calls provided function to process all alarms created. |
 | <code><a href="#cdk-monitoring-constructs.LogMonitoringProps.property.logGroupName">logGroupName</a></code> | <code>string</code> | Name of the log group to monitor. |
+| <code><a href="#cdk-monitoring-constructs.LogMonitoringProps.property.addMaxIncomingLogsAlarm">addMaxIncomingLogsAlarm</a></code> | <code>{[ key: string ]: <a href="#cdk-monitoring-constructs.MaxUsageCountThreshold">MaxUsageCountThreshold</a>}</code> | *No description.* |
 | <code><a href="#cdk-monitoring-constructs.LogMonitoringProps.property.addMinIncomingLogsAlarm">addMinIncomingLogsAlarm</a></code> | <code>{[ key: string ]: <a href="#cdk-monitoring-constructs.MinUsageCountThreshold">MinUsageCountThreshold</a>}</code> | *No description.* |
 | <code><a href="#cdk-monitoring-constructs.LogMonitoringProps.property.limit">limit</a></code> | <code>number</code> | Maximum number of log messages to search for. |
 | <code><a href="#cdk-monitoring-constructs.LogMonitoringProps.property.pattern">pattern</a></code> | <code>string</code> | Pattern to search for, e.g. "ERROR". |
@@ -25323,6 +25324,16 @@ Name of the log group to monitor.
 
 ---
 
+##### `addMaxIncomingLogsAlarm`<sup>Optional</sup> <a name="addMaxIncomingLogsAlarm" id="cdk-monitoring-constructs.LogMonitoringProps.property.addMaxIncomingLogsAlarm"></a>
+
+```typescript
+public readonly addMaxIncomingLogsAlarm: {[ key: string ]: MaxUsageCountThreshold};
+```
+
+- *Type:* {[ key: string ]: <a href="#cdk-monitoring-constructs.MaxUsageCountThreshold">MaxUsageCountThreshold</a>}
+
+---
+
 ##### `addMinIncomingLogsAlarm`<sup>Optional</sup> <a name="addMinIncomingLogsAlarm" id="cdk-monitoring-constructs.LogMonitoringProps.property.addMinIncomingLogsAlarm"></a>
 
 ```typescript
diff --git a/lib/monitoring/aws-cloudwatch/LogMonitoring.ts b/lib/monitoring/aws-cloudwatch/LogMonitoring.ts
index 9f9c679c..e37b1ffc 100644
--- a/lib/monitoring/aws-cloudwatch/LogMonitoring.ts
+++ b/lib/monitoring/aws-cloudwatch/LogMonitoring.ts
@@ -17,6 +17,7 @@ import {
   DefaultLogWidgetHeight,
   DefaultSummaryWidgetHeight,
   FullWidth,
+  MaxUsageCountThreshold,
   MetricWithAlarmSupport,
   MinUsageCountThreshold,
   Monitoring,
@@ -55,6 +56,7 @@ export interface LogMonitoringProps
   readonly limit?: number;
 
   readonly addMinIncomingLogsAlarm?: Record<string, MinUsageCountThreshold>;
+  readonly addMaxIncomingLogsAlarm?: Record<string, MaxUsageCountThreshold>;
 }
 
 /**
@@ -116,6 +118,17 @@ export class LogMonitoring extends Monitoring {
       this.addAlarm(createdAlarm);
     }
 
+    for (const disambiguator in props.addMaxIncomingLogsAlarm) {
+      const alarmProps = props.addMaxIncomingLogsAlarm[disambiguator];
+      const createdAlarm = this.usageAlarmFactory.addMaxCountAlarm(
+        this.incomingLogEventsMetric,
+        alarmProps,
+        disambiguator
+      );
+      this.usageAnnotations.push(createdAlarm.annotation);
+      this.addAlarm(createdAlarm);
+    }
+
     props.useCreatedAlarms?.consume(this.createdAlarms());
   }
 


Test patch:
diff --git a/test/monitoring/aws-cloudwatch/LogMonitoring.test.ts b/test/monitoring/aws-cloudwatch/LogMonitoring.test.ts
index 309d8a12..e474656e 100644
--- a/test/monitoring/aws-cloudwatch/LogMonitoring.test.ts
+++ b/test/monitoring/aws-cloudwatch/LogMonitoring.test.ts
@@ -65,6 +65,11 @@ test("snapshot test: with alarms", () => {
         treatMissingDataOverride: TreatMissingData.BREACHING,
       },
     },
+    addMaxIncomingLogsAlarm: {
+      Critical: {
+        maxCount: 9001,
+      },
+    },
     useCreatedAlarms: {
       consume(alarms) {
         numAlarmsCreated = alarms.length;
@@ -73,6 +78,6 @@ test("snapshot test: with alarms", () => {
   });
 
   addMonitoringDashboardsToStack(stack, monitoring);
-  expect(numAlarmsCreated).toStrictEqual(1);
+  expect(numAlarmsCreated).toStrictEqual(2);
   expect(Template.fromStack(stack)).toMatchSnapshot();
 });
diff --git a/test/monitoring/aws-cloudwatch/__snapshots__/LogMonitoring.test.ts.snap b/test/monitoring/aws-cloudwatch/__snapshots__/LogMonitoring.test.ts.snap
index ee793f33..79130ea8 100644
--- a/test/monitoring/aws-cloudwatch/__snapshots__/LogMonitoring.test.ts.snap
+++ b/test/monitoring/aws-cloudwatch/__snapshots__/LogMonitoring.test.ts.snap
@@ -278,6 +278,17 @@ Object {
                   "Arn",
                 ],
               },
+              "\\"]},\\"yAxis\\":{}}},{\\"type\\":\\"metric\\",\\"width\\":6,\\"height\\":4,\\"x\\":6,\\"y\\":0,\\"properties\\":{\\"view\\":\\"timeSeries\\",\\"region\\":\\"",
+              Object {
+                "Ref": "AWS::Region",
+              },
+              "\\",\\"annotations\\":{\\"alarms\\":[\\"",
+              Object {
+                "Fn::GetAtt": Array [
+                  "ScopeTestDummyLogGroupMaxUsageCountCriticalD4E65812",
+                  "Arn",
+                ],
+              },
               "\\"]},\\"yAxis\\":{}}}]}",
             ],
           ],
@@ -299,13 +310,47 @@ Object {
               Object {
                 "Ref": "AWS::Region",
               },
-              "\\",\\"metrics\\":[[\\"AWS/Logs\\",\\"IncomingLogEvents\\",\\"LogGroupName\\",\\"DummyLogGroup\\",{\\"label\\":\\"Logs\\",\\"stat\\":\\"SampleCount\\"}]],\\"annotations\\":{\\"horizontal\\":[{\\"label\\":\\"Logs < 20 for 3 datapoints within 15 minutes\\",\\"value\\":20,\\"yAxis\\":\\"left\\"}]},\\"yAxis\\":{\\"left\\":{\\"min\\":0,\\"label\\":\\"Count\\",\\"showUnits\\":false}}}}]}",
+              "\\",\\"metrics\\":[[\\"AWS/Logs\\",\\"IncomingLogEvents\\",\\"LogGroupName\\",\\"DummyLogGroup\\",{\\"label\\":\\"Logs\\",\\"stat\\":\\"SampleCount\\"}]],\\"annotations\\":{\\"horizontal\\":[{\\"label\\":\\"Logs < 20 for 3 datapoints within 15 minutes\\",\\"value\\":20,\\"yAxis\\":\\"left\\"},{\\"label\\":\\"Logs > 9001 for 3 datapoints within 15 minutes\\",\\"value\\":9001,\\"yAxis\\":\\"left\\"}]},\\"yAxis\\":{\\"left\\":{\\"min\\":0,\\"label\\":\\"Count\\",\\"showUnits\\":false}}}}]}",
             ],
           ],
         },
       },
       "Type": "AWS::CloudWatch::Dashboard",
     },
+    "ScopeTestDummyLogGroupMaxUsageCountCriticalD4E65812": Object {
+      "Properties": Object {
+        "ActionsEnabled": true,
+        "AlarmDescription": "The count is too high.",
+        "AlarmName": "Test-DummyLogGroup-Max-Usage-Count-Critical",
+        "ComparisonOperator": "GreaterThanThreshold",
+        "DatapointsToAlarm": 3,
+        "EvaluationPeriods": 3,
+        "Metrics": Array [
+          Object {
+            "Id": "m1",
+            "Label": "Logs",
+            "MetricStat": Object {
+              "Metric": Object {
+                "Dimensions": Array [
+                  Object {
+                    "Name": "LogGroupName",
+                    "Value": "DummyLogGroup",
+                  },
+                ],
+                "MetricName": "IncomingLogEvents",
+                "Namespace": "AWS/Logs",
+              },
+              "Period": 300,
+              "Stat": "SampleCount",
+            },
+            "ReturnData": true,
+          },
+        ],
+        "Threshold": 9001,
+        "TreatMissingData": "missing",
+      },
+      "Type": "AWS::CloudWatch::Alarm",
+    },
     "ScopeTestDummyLogGroupUsageCountWarningAE5FF03C": Object {
       "Properties": Object {
         "ActionsEnabled": true,
@@ -350,7 +395,7 @@ Object {
               Object {
                 "Ref": "AWS::Region",
               },
-              "\\",\\"metrics\\":[[\\"AWS/Logs\\",\\"IncomingLogEvents\\",\\"LogGroupName\\",\\"DummyLogGroup\\",{\\"label\\":\\"Logs\\",\\"stat\\":\\"SampleCount\\"}]],\\"annotations\\":{\\"horizontal\\":[{\\"label\\":\\"Logs < 20 for 3 datapoints within 15 minutes\\",\\"value\\":20,\\"yAxis\\":\\"left\\"}]},\\"yAxis\\":{\\"left\\":{\\"min\\":0,\\"label\\":\\"Count\\",\\"showUnits\\":false}}}}]}",
+              "\\",\\"metrics\\":[[\\"AWS/Logs\\",\\"IncomingLogEvents\\",\\"LogGroupName\\",\\"DummyLogGroup\\",{\\"label\\":\\"Logs\\",\\"stat\\":\\"SampleCount\\"}]],\\"annotations\\":{\\"horizontal\\":[{\\"label\\":\\"Logs < 20 for 3 datapoints within 15 minutes\\",\\"value\\":20,\\"yAxis\\":\\"left\\"},{\\"label\\":\\"Logs > 9001 for 3 datapoints within 15 minutes\\",\\"value\\":9001,\\"yAxis\\":\\"left\\"}]},\\"yAxis\\":{\\"left\\":{\\"min\\":0,\\"label\\":\\"Count\\",\\"showUnits\\":false}}}}]}",
             ],
           ],
         },