|
12 | 12 | from aws_lambda_powertools.metrics.base import single_metric
|
13 | 13 | from aws_lambda_powertools.metrics.exceptions import MetricValueError, SchemaValidationError
|
14 | 14 | from aws_lambda_powertools.metrics.functions import (
|
| 15 | + convert_timestamp_to_emf_format, |
15 | 16 | extract_cloudwatch_metric_resolution_value,
|
16 | 17 | extract_cloudwatch_metric_unit_value,
|
| 18 | + validate_emf_timestamp, |
17 | 19 | )
|
18 | 20 | from aws_lambda_powertools.metrics.provider.base import BaseProvider
|
19 | 21 | from aws_lambda_powertools.metrics.provider.cloudwatch_emf.constants import MAX_DIMENSIONS, MAX_METRICS
|
@@ -73,6 +75,7 @@ def __init__(
|
73 | 75 | self.namespace = resolve_env_var_choice(choice=namespace, env=os.getenv(constants.METRICS_NAMESPACE_ENV))
|
74 | 76 | self.service = resolve_env_var_choice(choice=service, env=os.getenv(constants.SERVICE_NAME_ENV))
|
75 | 77 | self.metadata_set = metadata_set if metadata_set is not None else {}
|
| 78 | + self.timestamp: int | None = None |
76 | 79 |
|
77 | 80 | self._metric_units = [unit.value for unit in MetricUnit]
|
78 | 81 | self._metric_unit_valid_options = list(MetricUnit.__members__)
|
@@ -231,7 +234,7 @@ def serialize_metric_set(
|
231 | 234 |
|
232 | 235 | return {
|
233 | 236 | "_aws": {
|
234 |
| - "Timestamp": int(datetime.datetime.now().timestamp() * 1000), # epoch |
| 237 | + "Timestamp": self.timestamp or int(datetime.datetime.now().timestamp() * 1000), # epoch |
235 | 238 | "CloudWatchMetrics": [
|
236 | 239 | {
|
237 | 240 | "Namespace": self.namespace, # "test_namespace"
|
@@ -304,6 +307,31 @@ def add_metadata(self, key: str, value: Any) -> None:
|
304 | 307 | else:
|
305 | 308 | self.metadata_set[str(key)] = value
|
306 | 309 |
|
| 310 | + def set_timestamp(self, timestamp: int | datetime.datetime): |
| 311 | + """ |
| 312 | + Set the timestamp for the metric. |
| 313 | +
|
| 314 | + Parameters: |
| 315 | + ----------- |
| 316 | + timestamp: int | datetime.datetime |
| 317 | + The timestamp to create the metric. |
| 318 | + If an integer is provided, it is assumed to be the epoch time in milliseconds. |
| 319 | + If a datetime object is provided, it will be converted to epoch time in milliseconds. |
| 320 | + """ |
| 321 | + # The timestamp must be a Datetime object or an integer representing an epoch time. |
| 322 | + # This should not exceed 14 days in the past or be more than 2 hours in the future. |
| 323 | + # Any metrics failing to meet this criteria will be skipped by Amazon CloudWatch. |
| 324 | + # See: https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Specification.html |
| 325 | + # See: https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CloudWatch-Logs-Monitoring-CloudWatch-Metrics.html |
| 326 | + if not validate_emf_timestamp(timestamp): |
| 327 | + warnings.warn( |
| 328 | + "This metric doesn't meet the requirements and will be skipped by Amazon CloudWatch. " |
| 329 | + "Ensure the timestamp is within 14 days past or 2 hours future.", |
| 330 | + stacklevel=2, |
| 331 | + ) |
| 332 | + |
| 333 | + self.timestamp = convert_timestamp_to_emf_format(timestamp) |
| 334 | + |
307 | 335 | def clear_metrics(self) -> None:
|
308 | 336 | logger.debug("Clearing out existing metric set from memory")
|
309 | 337 | self.metric_set.clear()
|
|
0 commit comments