Skip to content

Commit 5291912

Browse files
Refactoring code
1 parent 8b45169 commit 5291912

File tree

5 files changed

+180
-112
lines changed

5 files changed

+180
-112
lines changed

aws_lambda_powertools/utilities/data_classes/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88
from .aws_config_rule_event import AWSConfigRuleEvent
99
from .bedrock_agent_event import BedrockAgentEvent
1010
from .cloud_watch_alarm_event import (
11+
CloudWatchAlarmConfiguration,
1112
CloudWatchAlarmData,
1213
CloudWatchAlarmEvent,
1314
CloudWatchAlarmMetric,
15+
CloudWatchAlarmMetricStat,
1416
CloudWatchAlarmState,
1517
)
1618
from .cloud_watch_custom_widget_event import CloudWatchDashboardCustomWidgetEvent
@@ -52,6 +54,8 @@
5254
"CloudWatchAlarmEvent",
5355
"CloudWatchAlarmMetric",
5456
"CloudWatchAlarmState",
57+
"CloudWatchAlarmConfiguration",
58+
"CloudWatchAlarmMetricStat",
5559
"CloudWatchDashboardCustomWidgetEvent",
5660
"CloudWatchLogsEvent",
5761
"CodePipelineJobEvent",

aws_lambda_powertools/utilities/data_classes/cloud_watch_alarm_event.py

Lines changed: 72 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,28 @@
11
from __future__ import annotations
22

33
from functools import cached_property
4-
from typing import Any, List, Literal, Optional
4+
from typing import Any, Dict, List, Literal, Optional
55

66
from aws_lambda_powertools.utilities.data_classes.common import DictWrapper
77

8-
CloudWatchAlarmStateValue = Literal["OK", "ALARM", "INSUFFICIENT_DATA"]
9-
CloudWatchAlarmActionSuppressor = Literal["Alarm", "ExtensionPeriod", "WaitPeriod"]
10-
118

129
class CloudWatchAlarmState(DictWrapper):
1310
@property
14-
def value(self) -> CloudWatchAlarmStateValue:
11+
def value(self) -> Literal["OK", "ALARM", "INSUFFICIENT_DATA"]:
1512
"""
1613
Overall state of the alarm.
1714
"""
1815
return self["value"]
1916

2017
@property
21-
def reason(self) -> Optional[str]:
18+
def reason(self) -> str:
2219
"""
2320
Reason why alarm was changed to this state.
2421
"""
2522
return self.get("reason")
2623

2724
@property
28-
def reason_data(self) -> Optional[str]:
25+
def reason_data(self) -> str:
2926
"""
3027
Additional data to back up the reason, usually contains the evaluated data points,
3128
the calculated threshold and timestamps.
@@ -37,13 +34,11 @@ def reason_data_decoded(self) -> Optional[Any]:
3734
"""
3835
Deserialized version of reason_data.
3936
"""
40-
if self.reason_data is None:
41-
return None
4237

43-
return self._json_deserializer(self.reason_data)
38+
return self._json_deserializer(self.reason_data) if self.reason_data else None
4439

4540
@property
46-
def actions_suppressed_by(self) -> Optional[CloudWatchAlarmActionSuppressor]:
41+
def actions_suppressed_by(self) -> Optional[Literal["Alarm", "ExtensionPeriod", "WaitPeriod"]]:
4742
"""
4843
Describes why the actions when the value is `ALARM` are suppressed in a composite
4944
alarm.
@@ -66,11 +61,6 @@ def timestamp(self) -> str:
6661

6762

6863
class CloudWatchAlarmMetric(DictWrapper):
69-
def __init__(self, data: dict):
70-
super().__init__(data)
71-
72-
self._metric_stat: dict | None = self.get("metricStat")
73-
7464
@property
7565
def metric_id(self) -> str:
7666
"""
@@ -81,98 +71,67 @@ def metric_id(self) -> str:
8171
@property
8272
def expression(self) -> Optional[str]:
8373
"""
84-
The mathematical expression for calculating the metric, if applicable.
74+
Optional expression of the alarm metric.
8575
"""
8676
return self.get("expression", None)
8777

8878
@property
89-
def label(self) -> Optional[str]:
79+
def label(self) -> str:
9080
"""
91-
Optional label of the metric.
81+
Optional label of the alarm metric.
9282
"""
9383
return self.get("label", None)
9484

9585
@property
96-
def namespace(self) -> Optional[str]:
97-
"""
98-
Namespace of the correspondent CloudWatch Metric.
99-
"""
100-
if self._metric_stat is not None:
101-
return self._metric_stat.get("metric", {}).get("namespace", None)
102-
103-
return None
104-
105-
@property
106-
def name(self) -> Optional[str]:
86+
def return_data(self) -> bool:
10787
"""
108-
Name of the correspondent CloudWatch Metric.
88+
Whether this metric data is used to determine the state of the alarm or not.
10989
"""
110-
if self._metric_stat is not None:
111-
return self._metric_stat.get("metric", {}).get("name", None)
112-
113-
return None
90+
return self["returnData"]
11491

11592
@property
116-
def dimensions(self) -> Optional[dict]:
117-
"""
118-
Additional dimensions of the correspondent CloudWatch Metric, if available.
119-
"""
120-
if self._metric_stat is not None:
121-
return self._metric_stat.get("metric", {}).get("dimensions", None)
93+
def metric_stat(self) -> CloudWatchAlarmMetricStat:
94+
return CloudWatchAlarmMetricStat(self["metricStat"])
12295

123-
return None
12496

97+
class CloudWatchAlarmMetricStat(DictWrapper):
12598
@property
12699
def period(self) -> Optional[int]:
127100
"""
128101
Metric evaluation period, in seconds.
129102
"""
130-
if self._metric_stat is not None:
131-
return self._metric_stat.get("period", None)
132-
133-
return None
103+
return self.get("period", None)
134104

135105
@property
136106
def stat(self) -> Optional[str]:
137107
"""
138108
Statistical aggregation of metric points, e.g. Average, SampleCount, etc.
139109
"""
140-
if self._metric_stat is not None:
141-
return self._metric_stat.get("stat", None)
110+
return self.get("stat", None)
142111

143-
return None
112+
@property
113+
def unit(self) -> Optional[str]:
114+
"""
115+
Unit for metric.
116+
"""
117+
return self.get("unit", None)
144118

145119
@property
146-
def return_data(self) -> bool:
120+
def metric(self) -> Dict:
147121
"""
148-
Whether this metric data is used to determine the state of the alarm or not.
122+
Metric details
149123
"""
150-
return self["returnData"]
124+
return self.get("metric", {})
151125

152126

153127
class CloudWatchAlarmData(DictWrapper):
154-
def __init__(self, data: dict):
155-
super().__init__(data)
156-
157-
self._configuration = self.get("configuration", None)
158-
159128
@property
160-
def name(self) -> str:
129+
def alarm_name(self) -> str:
161130
"""
162131
Alarm name.
163132
"""
164133
return self["alarmName"]
165134

166-
@property
167-
def description(self) -> Optional[str]:
168-
"""
169-
Optional description for the Alarm.
170-
"""
171-
if self._configuration is not None:
172-
return self._configuration.get("description", None)
173-
174-
return None
175-
176135
@property
177136
def state(self) -> CloudWatchAlarmState:
178137
"""
@@ -188,19 +147,56 @@ def previous_state(self) -> CloudWatchAlarmState:
188147
return CloudWatchAlarmState(self["previousState"])
189148

190149
@property
191-
def metrics(self) -> Optional[List[CloudWatchAlarmMetric]]:
150+
def configuration(self) -> CloudWatchAlarmConfiguration:
192151
"""
193-
The metrics evaluated for the Alarm.
152+
The configuration of the Alarm.
194153
"""
195-
if self._configuration is None:
196-
return None
154+
return CloudWatchAlarmConfiguration(self["configuration"])
197155

198-
maybe_metrics = self._configuration.get("metrics", None)
199156

200-
if maybe_metrics is not None:
201-
return [CloudWatchAlarmMetric(i) for i in maybe_metrics]
157+
class CloudWatchAlarmConfiguration(DictWrapper):
158+
@property
159+
def description(self) -> Optional[str]:
160+
"""
161+
Optional description for the Alarm.
162+
"""
163+
return self.get("description", None)
202164

203-
return None
165+
@property
166+
def alarm_rule(self) -> Optional[str]:
167+
"""
168+
Optional description for the Alarm rule in case of composite alarm.
169+
"""
170+
return self.get("alarmRule", None)
171+
172+
@property
173+
def alarm_actions_suppressor(self) -> Optional[str]:
174+
"""
175+
Optional action suppression for the Alarm rule in case of composite alarm.
176+
"""
177+
return self.get("actionsSuppressor", None)
178+
179+
@property
180+
def alarm_actions_suppressor_wait_period(self) -> Optional[str]:
181+
"""
182+
Optional action suppression wait period for the Alarm rule in case of composite alarm.
183+
"""
184+
return self.get("actionsSuppressorWaitPeriod", None)
185+
186+
@property
187+
def alarm_actions_suppressor_extension_period(self) -> Optional[str]:
188+
"""
189+
Optional action suppression extension period for the Alarm rule in case of composite alarm.
190+
"""
191+
return self.get("actionsSuppressorExtensionPeriod", None)
192+
193+
@property
194+
def metrics(self) -> Optional[List[CloudWatchAlarmMetric]]:
195+
"""
196+
The metrics evaluated for the Alarm.
197+
"""
198+
metrics = self.get("metrics")
199+
return [CloudWatchAlarmMetric(i) for i in metrics] if metrics else None
204200

205201

206202
class CloudWatchAlarmEvent(DictWrapper):
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"source":"aws.cloudwatch",
3+
"alarmArn":"arn:aws:cloudwatch:us-east-1:111122223333:alarm:SuppressionDemo.Main",
4+
"accountId":"111122223333",
5+
"time":"2023-08-04T12:56:46.138+0000",
6+
"region":"us-east-1",
7+
"alarmData":{
8+
"alarmName":"CompositeDemo.Main",
9+
"state":{
10+
"value":"ALARM",
11+
"reason":"arn:aws:cloudwatch:us-east-1:111122223333:alarm:CompositeDemo.FirstChild transitioned to ALARM at Friday 04 August, 2023 12:54:46 UTC",
12+
"reasonData":"{\"triggeringAlarms\":[{\"arn\":\"arn:aws:cloudwatch:us-east-1:111122223333:alarm:CompositeDemo.FirstChild\",\"state\":{\"value\":\"ALARM\",\"timestamp\":\"2023-08-04T12:54:46.138+0000\"}}]}",
13+
"timestamp":"2023-08-04T12:56:46.138+0000"
14+
},
15+
"previousState":{
16+
"value":"ALARM",
17+
"reason":"arn:aws:cloudwatch:us-east-1:111122223333:alarm:CompositeDemo.FirstChild transitioned to ALARM at Friday 04 August, 2023 12:54:46 UTC",
18+
"reasonData":"{\"triggeringAlarms\":[{\"arn\":\"arn:aws:cloudwatch:us-east-1:111122223333:alarm:CompositeDemo.FirstChild\",\"state\":{\"value\":\"ALARM\",\"timestamp\":\"2023-08-04T12:54:46.138+0000\"}}]}",
19+
"timestamp":"2023-08-04T12:54:46.138+0000",
20+
"actionsSuppressedBy":"WaitPeriod",
21+
"actionsSuppressedReason":"Actions suppressed by WaitPeriod"
22+
},
23+
"configuration":{
24+
"alarmRule":"ALARM(CompositeDemo.FirstChild) OR ALARM(CompositeDemo.SecondChild)",
25+
"actionsSuppressor":"CompositeDemo.ActionsSuppressor",
26+
"actionsSuppressorWaitPeriod":120,
27+
"actionsSuppressorExtensionPeriod":180
28+
}
29+
}
30+
}

tests/events/cloudWatchAlarmEvent.json renamed to tests/events/cloudWatchAlarmEventSingleMetric.json

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@
1616
"value": "OK",
1717
"reason": "Threshold Crossed: 1 out of the last 1 datapoints [1.0 (17/02/24 11:50:00)] was not greater than the threshold (10.0) (minimum 1 datapoint for ALARM -> OK transition).",
1818
"reasonData": "{\"version\":\"1.0\",\"queryDate\":\"2024-02-17T11:51:31.460+0000\",\"startDate\":\"2024-02-17T11:50:00.000+0000\",\"statistic\":\"SampleCount\",\"period\":60,\"recentDatapoints\":[1.0],\"threshold\":10.0,\"evaluatedDatapoints\":[{\"timestamp\":\"2024-02-17T11:50:00.000+0000\",\"sampleCount\":1.0,\"value\":1.0}]}",
19-
"timestamp": "2024-02-17T11:51:31.462+0000",
20-
"actionsSuppressedBy": "WaitPeriod",
21-
"actionsSuppressedReason": "Actions suppressed by WaitPeriod"
19+
"timestamp": "2024-02-17T11:51:31.462+0000"
2220
},
2321
"configuration": {
2422
"description": "This is description **here**",
@@ -58,4 +56,4 @@
5856
]
5957
}
6058
}
61-
}
59+
}

0 commit comments

Comments
 (0)