Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Object representations of the CloudWatch alarms #493

Merged
merged 1 commit into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading