Skip to content

Commit

Permalink
CloudWatch alarm events
Browse files Browse the repository at this point in the history
  • Loading branch information
msailes committed Jul 11, 2024
1 parent c0b4f60 commit aa9686f
Show file tree
Hide file tree
Showing 8 changed files with 389 additions and 2 deletions.
2 changes: 2 additions & 0 deletions aws-lambda-java-events/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
* `AppSyncLambdaAuthorizerResponse`
* `CloudFormationCustomResourceEvent`
* `CloudFrontEvent`
* `CloudWatchCompositeAlarmEvent`
* `CloudWatchLogsEvent`
* `CloudWatchMetricAlarmEvent`
* `CodeCommitEvent`
* `CognitoEvent`
* `CognitoUserPoolCreateAuthChallengeEvent`
Expand Down
2 changes: 2 additions & 0 deletions aws-lambda-java-events/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<lombok.version>1.18.22</lombok.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>

<distributionManagement>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.amazonaws.services.lambda.runtime.events;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
* Represents an CloudWatch Composite Alarm event. This event occurs when a composite alarm is triggered.
*
* @see <a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html#alarms-and-actions">Using Amazon CloudWatch alarms</a>
*/
@Data
@Builder(setterPrefix = "with")
@NoArgsConstructor
@AllArgsConstructor
public class CloudWatchCompositeAlarmEvent {
private String source;
private String alarmArn;
private String accountId;
private String time;
private String region;
private AlarmData alarmData;

@Data
@Builder(setterPrefix = "with")
@NoArgsConstructor
@AllArgsConstructor
public static class AlarmData {
private String alarmName;
private State state;
private PreviousState previousState;
private Configuration configuration;
}

@Data
@Builder(setterPrefix = "with")
@NoArgsConstructor
@AllArgsConstructor
public static class State {
private String value;
private String reason;
private String reasonData;
private String timestamp;
}

@Data
@Builder(setterPrefix = "with")
@NoArgsConstructor
@AllArgsConstructor
public static class PreviousState {
private String value;
private String reason;
private String reasonData;
private String timestamp;
private String actionsSuppressedBy;
private String actionsSuppressedReason;
}

@Data
@Builder(setterPrefix = "with")
@NoArgsConstructor
@AllArgsConstructor
public static class Configuration {
private String alarmRule;
private String actionsSuppressor;
private Integer actionsSuppressorWaitPeriod;
private Integer actionsSuppressorExtensionPeriod;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package com.amazonaws.services.lambda.runtime.events;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;
import java.util.Map;

/**
* Represents an CloudWatch Metric Alarm event. This event occurs when a metric alarm is triggered.
*
* @see <a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html#alarms-and-actions">Using Amazon CloudWatch alarms</a>
*/
@Data
@Builder(setterPrefix = "with")
@NoArgsConstructor
@AllArgsConstructor
public class CloudWatchMetricAlarmEvent {
private String source;
private String alarmArn;
private String accountId;
private String time;
private String region;
private AlarmData alarmData;

@Data
@Builder(setterPrefix = "with")
@NoArgsConstructor
@AllArgsConstructor
public static class AlarmData {
private String alarmName;
private State state;
private PreviousState previousState;
private Configuration configuration;
}

@Data
@Builder(setterPrefix = "with")
@NoArgsConstructor
@AllArgsConstructor
public static class State {
private String value;
private String reason;
private String timestamp;
}

@Data
@Builder(setterPrefix = "with")
@NoArgsConstructor
@AllArgsConstructor
public static class PreviousState {
private String value;
private String reason;
private String reasonData;
private String timestamp;
}

@Data
@Builder(setterPrefix = "with")
@NoArgsConstructor
@AllArgsConstructor
public static class Configuration {
private String description;
private List<Metric> metrics;
}

@Data
@Builder(setterPrefix = "with")
@NoArgsConstructor
@AllArgsConstructor
public static class Metric {
private String id;
private MetricStat metricStat;
private Boolean returnData;
}

@Data
@Builder(setterPrefix = "with")
@NoArgsConstructor
@AllArgsConstructor
public static class MetricStat {
private MetricDetail metric;
private Integer period;
private String stat;
private String unit;
}

@Data
@Builder(setterPrefix = "with")
@NoArgsConstructor
@AllArgsConstructor
public static class MetricDetail {
private String namespace;
private String name;
private Map<String, String> dimensions;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,18 @@ public static CloudFrontEvent loadCloudFrontEvent(String filename) {
return loadEvent(filename, CloudFrontEvent.class);
}

public static CloudWatchCompositeAlarmEvent loadCloudWatchCompositeAlarmEvent(String filename) {
return loadEvent(filename, CloudWatchCompositeAlarmEvent.class);
}

public static CloudWatchLogsEvent loadCloudWatchLogsEvent(String filename) {
return loadEvent(filename, CloudWatchLogsEvent.class);
}

public static CloudWatchMetricAlarmEvent loadCloudWatchMetricAlarmEvent(String filename) {
return loadEvent(filename, CloudWatchMetricAlarmEvent.class);
}

public static CodeCommitEvent loadCodeCommitEvent(String filename) {
return loadEvent(filename, CodeCommitEvent.class);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,38 @@
/* Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. */
package com.amazonaws.services.lambda.runtime.tests;

import com.amazonaws.services.lambda.runtime.events.APIGatewayCustomAuthorizerEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayV2CustomAuthorizerEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent;
import com.amazonaws.services.lambda.runtime.events.ActiveMQEvent;
import com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent;
import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent;
import com.amazonaws.services.lambda.runtime.events.CloudFrontEvent;
import com.amazonaws.services.lambda.runtime.events.CloudWatchCompositeAlarmEvent;
import com.amazonaws.services.lambda.runtime.events.CloudWatchCompositeAlarmEvent.AlarmData;
import com.amazonaws.services.lambda.runtime.events.CloudWatchCompositeAlarmEvent.Configuration;
import com.amazonaws.services.lambda.runtime.events.CloudWatchCompositeAlarmEvent.PreviousState;
import com.amazonaws.services.lambda.runtime.events.CloudWatchCompositeAlarmEvent.State;
import com.amazonaws.services.lambda.runtime.events.CloudWatchLogsEvent;
import com.amazonaws.services.lambda.runtime.events.CloudWatchMetricAlarmEvent;
import com.amazonaws.services.lambda.runtime.events.CodeCommitEvent;
import com.amazonaws.services.lambda.runtime.events.CognitoUserPoolPreTokenGenerationEventV2;
import com.amazonaws.services.lambda.runtime.events.ConfigEvent;
import com.amazonaws.services.lambda.runtime.events.ConnectEvent;
import com.amazonaws.services.lambda.runtime.events.DynamodbEvent;
import com.amazonaws.services.lambda.runtime.events.KafkaEvent;
import com.amazonaws.services.lambda.runtime.events.KinesisEvent;
import com.amazonaws.services.lambda.runtime.events.KinesisFirehoseEvent;
import com.amazonaws.services.lambda.runtime.events.LambdaDestinationEvent;
import com.amazonaws.services.lambda.runtime.events.LexEvent;
import com.amazonaws.services.lambda.runtime.events.MSKFirehoseEvent;
import com.amazonaws.services.lambda.runtime.events.RabbitMQEvent;
import com.amazonaws.services.lambda.runtime.events.S3Event;
import com.amazonaws.services.lambda.runtime.events.SNSEvent;
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
import com.amazonaws.services.lambda.runtime.events.ScheduledEvent;
import com.amazonaws.services.lambda.runtime.events.SecretsManagerRotationEvent;
import com.amazonaws.services.lambda.runtime.events.models.dynamodb.AttributeValue;
import com.amazonaws.services.lambda.runtime.events.models.dynamodb.Record;
import com.amazonaws.services.lambda.runtime.events.models.dynamodb.StreamRecord;
Expand All @@ -15,8 +47,6 @@
import static java.time.Instant.ofEpochSecond;
import static org.assertj.core.api.Assertions.*;

import com.amazonaws.services.lambda.runtime.events.*;

public class EventLoaderTest {

@Test
Expand Down Expand Up @@ -389,4 +419,108 @@ public void testLoadCognitoUserPoolPreTokenGenerationEventV2() {
String[] requestScopes = request.getScopes();
assertThat("aws.cognito.signin.user.admin").isEqualTo(requestScopes[0]);
}

@Test
public void testCloudWatchCompositeAlarmEvent() {
CloudWatchCompositeAlarmEvent event = EventLoader.loadCloudWatchCompositeAlarmEvent("cloudwatch_composite_alarm.json");
assertThat(event).isNotNull();
assertThat(event)
.returns("aws.cloudwatch", from(CloudWatchCompositeAlarmEvent::getSource))
.returns("arn:aws:cloudwatch:us-east-1:111122223333:alarm:SuppressionDemo.Main", from(CloudWatchCompositeAlarmEvent::getAlarmArn))
.returns("111122223333", from(CloudWatchCompositeAlarmEvent::getAccountId))
.returns("2023-08-04T12:56:46.138+0000", from(CloudWatchCompositeAlarmEvent::getTime))
.returns("us-east-1", from(CloudWatchCompositeAlarmEvent::getRegion));

AlarmData alarmData = event.getAlarmData();
assertThat(alarmData).isNotNull();
assertThat(alarmData)
.returns("CompositeDemo.Main", from(AlarmData::getAlarmName));

State state = alarmData.getState();
assertThat(state).isNotNull();
assertThat(state)
.returns("ALARM", from(State::getValue))
.returns("arn:aws:cloudwatch:us-east-1:111122223333:alarm:CompositeDemo.FirstChild transitioned to ALARM at Friday 04 August, 2023 12:54:46 UTC", from(State::getReason))
.returns("{\"triggeringAlarms\":[{\"arn\":\"arn:aws:cloudwatch:us-east-1:111122223333:alarm:CompositeDemo.FirstChild\",\"state\":{\"value\":\"ALARM\",\"timestamp\":\"2023-08-04T12:54:46.138+0000\"}}]}", from(State::getReasonData))
.returns("2023-08-04T12:56:46.138+0000", from(State::getTimestamp));

PreviousState previousState = alarmData.getPreviousState();
assertThat(previousState).isNotNull();
assertThat(previousState)
.returns("ALARM", from(PreviousState::getValue))
.returns("arn:aws:cloudwatch:us-east-1:111122223333:alarm:CompositeDemo.FirstChild transitioned to ALARM at Friday 04 August, 2023 12:54:46 UTC", from(PreviousState::getReason))
.returns("{\"triggeringAlarms\":[{\"arn\":\"arn:aws:cloudwatch:us-east-1:111122223333:alarm:CompositeDemo.FirstChild\",\"state\":{\"value\":\"ALARM\",\"timestamp\":\"2023-08-04T12:54:46.138+0000\"}}]}", from(PreviousState::getReasonData))
.returns("2023-08-04T12:54:46.138+0000", from(PreviousState::getTimestamp))
.returns("WaitPeriod", from(PreviousState::getActionsSuppressedBy))
.returns("Actions suppressed by WaitPeriod", from(PreviousState::getActionsSuppressedReason));

Configuration configuration = alarmData.getConfiguration();
assertThat(configuration).isNotNull();
assertThat(configuration)
.returns("ALARM(CompositeDemo.FirstChild) OR ALARM(CompositeDemo.SecondChild)", from(Configuration::getAlarmRule))
.returns("CompositeDemo.ActionsSuppressor", from(Configuration::getActionsSuppressor))
.returns(120, from(Configuration::getActionsSuppressorWaitPeriod))
.returns(180, from(Configuration::getActionsSuppressorExtensionPeriod));
}

@Test
public void testCloudWatchMetricAlarmEvent() {
CloudWatchMetricAlarmEvent event = EventLoader.loadCloudWatchMetricAlarmEvent("cloudwatch_metric_alarm.json");
assertThat(event).isNotNull();
assertThat(event)
.returns("aws.cloudwatch", from(CloudWatchMetricAlarmEvent::getSource))
.returns("arn:aws:cloudwatch:us-east-1:444455556666:alarm:lambda-demo-metric-alarm", from(CloudWatchMetricAlarmEvent::getAlarmArn))
.returns("444455556666", from(CloudWatchMetricAlarmEvent::getAccountId))
.returns("2023-08-04T12:36:15.490+0000", from(CloudWatchMetricAlarmEvent::getTime))
.returns("us-east-1", from(CloudWatchMetricAlarmEvent::getRegion));

CloudWatchMetricAlarmEvent.AlarmData alarmData = event.getAlarmData();
assertThat(alarmData).isNotNull();
assertThat(alarmData)
.returns("lambda-demo-metric-alarm", from(CloudWatchMetricAlarmEvent.AlarmData::getAlarmName));

CloudWatchMetricAlarmEvent.State state = alarmData.getState();
assertThat(state).isNotNull();
assertThat(state)
.returns("ALARM", from(CloudWatchMetricAlarmEvent.State::getValue))
.returns("test", from(CloudWatchMetricAlarmEvent.State::getReason))
.returns("2023-08-04T12:36:15.490+0000", from(CloudWatchMetricAlarmEvent.State::getTimestamp));

CloudWatchMetricAlarmEvent.PreviousState previousState = alarmData.getPreviousState();
assertThat(previousState).isNotNull();
assertThat(previousState)
.returns("INSUFFICIENT_DATA", from(CloudWatchMetricAlarmEvent.PreviousState::getValue))
.returns("Insufficient Data: 5 datapoints were unknown.", from(CloudWatchMetricAlarmEvent.PreviousState::getReason))
.returns("{\"version\":\"1.0\",\"queryDate\":\"2023-08-04T12:31:29.591+0000\",\"statistic\":\"Average\",\"period\":60,\"recentDatapoints\":[],\"threshold\":5.0,\"evaluatedDatapoints\":[{\"timestamp\":\"2023-08-04T12:30:00.000+0000\"},{\"timestamp\":\"2023-08-04T12:29:00.000+0000\"},{\"timestamp\":\"2023-08-04T12:28:00.000+0000\"},{\"timestamp\":\"2023-08-04T12:27:00.000+0000\"},{\"timestamp\":\"2023-08-04T12:26:00.000+0000\"}]}", from(CloudWatchMetricAlarmEvent.PreviousState::getReasonData))
.returns("2023-08-04T12:31:29.595+0000", from(CloudWatchMetricAlarmEvent.PreviousState::getTimestamp));

CloudWatchMetricAlarmEvent.Configuration configuration = alarmData.getConfiguration();
assertThat(configuration).isNotNull();
assertThat(configuration)
.returns("Metric Alarm to test Lambda actions", from(CloudWatchMetricAlarmEvent.Configuration::getDescription));

List<CloudWatchMetricAlarmEvent.Metric> metrics = configuration.getMetrics();
assertThat(metrics).hasSize(1);
CloudWatchMetricAlarmEvent.Metric metric = metrics.get(0);
assertThat(metric)
.returns("1234e046-06f0-a3da-9534-EXAMPLEe4c", from(CloudWatchMetricAlarmEvent.Metric::getId));

CloudWatchMetricAlarmEvent.MetricStat metricStat = metric.getMetricStat();
assertThat(metricStat).isNotNull();
assertThat(metricStat)
.returns(60, from(CloudWatchMetricAlarmEvent.MetricStat::getPeriod))
.returns("Average", from(CloudWatchMetricAlarmEvent.MetricStat::getStat))
.returns("Percent", from(CloudWatchMetricAlarmEvent.MetricStat::getUnit));

CloudWatchMetricAlarmEvent.MetricDetail metricDetail = metricStat.getMetric();
assertThat(metricDetail).isNotNull();
assertThat(metricDetail)
.returns("AWS/Logs", from(CloudWatchMetricAlarmEvent.MetricDetail::getNamespace))
.returns("CallCount", from(CloudWatchMetricAlarmEvent.MetricDetail::getName));

Map<String, String> dimensions = metricDetail.getDimensions();
assertThat(dimensions).isNotEmpty().hasSize(1);
assertThat(dimensions)
.contains(entry("InstanceId", "i-12345678"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"source": "aws.cloudwatch",
"alarmArn": "arn:aws:cloudwatch:us-east-1:111122223333:alarm:SuppressionDemo.Main",
"accountId": "111122223333",
"time": "2023-08-04T12:56:46.138+0000",
"region": "us-east-1",
"alarmData": {
"alarmName": "CompositeDemo.Main",
"state": {
"value": "ALARM",
"reason": "arn:aws:cloudwatch:us-east-1:111122223333:alarm:CompositeDemo.FirstChild transitioned to ALARM at Friday 04 August, 2023 12:54:46 UTC",
"reasonData": "{\"triggeringAlarms\":[{\"arn\":\"arn:aws:cloudwatch:us-east-1:111122223333:alarm:CompositeDemo.FirstChild\",\"state\":{\"value\":\"ALARM\",\"timestamp\":\"2023-08-04T12:54:46.138+0000\"}}]}",
"timestamp": "2023-08-04T12:56:46.138+0000"
},
"previousState": {
"value": "ALARM",
"reason": "arn:aws:cloudwatch:us-east-1:111122223333:alarm:CompositeDemo.FirstChild transitioned to ALARM at Friday 04 August, 2023 12:54:46 UTC",
"reasonData": "{\"triggeringAlarms\":[{\"arn\":\"arn:aws:cloudwatch:us-east-1:111122223333:alarm:CompositeDemo.FirstChild\",\"state\":{\"value\":\"ALARM\",\"timestamp\":\"2023-08-04T12:54:46.138+0000\"}}]}",
"timestamp": "2023-08-04T12:54:46.138+0000",
"actionsSuppressedBy": "WaitPeriod",
"actionsSuppressedReason": "Actions suppressed by WaitPeriod"
},
"configuration": {
"alarmRule": "ALARM(CompositeDemo.FirstChild) OR ALARM(CompositeDemo.SecondChild)",
"actionsSuppressor": "CompositeDemo.ActionsSuppressor",
"actionsSuppressorWaitPeriod": 120,
"actionsSuppressorExtensionPeriod": 180
}
}
}
Loading

0 comments on commit aa9686f

Please sign in to comment.