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

feat(metrics): support to bring your own metrics provider #2194

Merged
merged 54 commits into from
Aug 1, 2023
Merged
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
b9f8cea
Use a different Metric class for different provider
roger-zhangg May 30, 2023
06c9c8e
fix static checking error
roger-zhangg May 30, 2023
10514f7
fix static checking error
roger-zhangg May 30, 2023
c9b018f
optimize docstring
roger-zhangg Jun 1, 2023
de7eb16
Merge branch 'awslabs:develop' into metrics
roger-zhangg Jun 5, 2023
efab535
Merge remote-tracking branch 'upstream/develop' into metrics
roger-zhangg Jun 6, 2023
5fd493a
Merge branch 'develop' into develop
roger-zhangg Jun 6, 2023
8dde509
Merge remote-tracking branch 'upstream/develop' into metrics
roger-zhangg Jun 12, 2023
58bc274
add alias CloudWatchEMF to original Metrics class
roger-zhangg Jun 12, 2023
4de8842
add alias CloudWatchEMF to original Metrics class
roger-zhangg Jun 12, 2023
ea4ec06
Merge remote-tracking branch 'origin/develop' into develop
roger-zhangg Jun 12, 2023
dafed9e
Merge branch 'develop' into develop
leandrodamascena Jun 13, 2023
fedb3a0
Move Metrics to Provider
roger-zhangg Jun 13, 2023
3bab2ae
Merge remote-tracking branch 'origin/develop' into develop
roger-zhangg Jun 13, 2023
169f02c
add sample document
roger-zhangg Jun 15, 2023
7bfd874
reformat code block
roger-zhangg Jun 15, 2023
f26e26d
add OTel provider draft for poc
roger-zhangg Jun 20, 2023
e015351
Merge branch 'develop' into develop
leandrodamascena Jun 27, 2023
5659cdd
rebasing from upstream
leandrodamascena Jun 27, 2023
1dab8d1
rebasing from upstream
leandrodamascena Jun 27, 2023
c203c3d
add test to metrics providers
roger-zhangg Jun 28, 2023
3045abc
merging from develop
leandrodamascena Jul 11, 2023
9cde8e3
docstring + code coverage
leandrodamascena Jul 11, 2023
5bdb2c2
python annotations + imports
leandrodamascena Jul 11, 2023
ab36099
changing the name to AmazonCloudWatchEMF
leandrodamascena Jul 12, 2023
4ee1b9e
Merge branch 'develop' into develop
leandrodamascena Jul 12, 2023
28531ac
Merge branch 'develop' into develop
leandrodamascena Jul 13, 2023
c223e65
Merge branch 'develop' into develop
leandrodamascena Jul 13, 2023
3673c4b
fix docstring
roger-zhangg Jul 13, 2023
93ba2bc
Merge remote-tracking branch 'origin/develop' into develop
roger-zhangg Jul 13, 2023
5c49b1e
add tests for datadog provider
roger-zhangg Jul 13, 2023
1540be7
add tests for datadog provider
roger-zhangg Jul 13, 2023
1f949aa
Merge branch 'develop' into develop
leandrodamascena Jul 19, 2023
190b112
Merge branch 'develop' into develop
leandrodamascena Jul 21, 2023
01972e5
migrate from ABC to protocol, support convert kwargs to tags, add test
roger-zhangg Jul 24, 2023
c31d41f
migrate from ABC to protocol, support convert kwargs to tags, add test
roger-zhangg Jul 24, 2023
3bebcad
migrate from ABC to protocol, support convert kwargs to tags, add test
roger-zhangg Jul 24, 2023
e7c1443
remove parent class, fix example
roger-zhangg Jul 25, 2023
7556782
Merge branch 'develop' into develop
leandrodamascena Jul 25, 2023
a904764
base: fix small problems
leandrodamascena Jul 27, 2023
58a25fb
refactoring: removing Datadog provider
leandrodamascena Jul 27, 2023
00e719d
Merge branch 'develop' into develop
leandrodamascena Jul 27, 2023
bdaa736
refactoring: importing from typing_extensions
leandrodamascena Jul 27, 2023
7ac42be
refactoring EMF provider
leandrodamascena Jul 27, 2023
294bd85
refactoring cloudwatchemf provider and cleaning code
leandrodamascena Jul 28, 2023
077d7e7
fix mypy error
leandrodamascena Jul 28, 2023
ae67adb
Merge remote-tracking branch 'upstream/develop' into roger-zhangg/dev…
leandrodamascena Jul 28, 2023
42517ed
fix mypy error
leandrodamascena Jul 28, 2023
28982a3
fix metric tests
leandrodamascena Jul 28, 2023
f798ab8
Merge branch 'develop' into develop
leandrodamascena Jul 28, 2023
7fe0641
Merge branch 'develop' into develop
leandrodamascena Jul 28, 2023
4592939
removing documentation
Aug 1, 2023
e8cfc81
fix documentation
Aug 1, 2023
92eda07
adding test
Aug 1, 2023
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
15 changes: 15 additions & 0 deletions .gitleaks.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Title for the gitleaks configuration file.
title = "Gitleaks"

[extend]
# useDefault will extend the base configuration with the default gitleaks config:
# https://github.com/zricethezav/gitleaks/blob/master/config/gitleaks.toml
useDefault = true

[allowlist]
description = "Allow list false positive"

# Allow list paths to ignore due to false positives.
paths = [
'''tests/unit/parser/test_kinesis_firehose\.py''',
]
15 changes: 7 additions & 8 deletions aws_lambda_powertools/metrics/__init__.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
"""CloudWatch Embedded Metric Format utility
"""
from .base import MetricResolution, MetricUnit
from .exceptions import (
from aws_lambda_powertools.metrics.base import MetricResolution, MetricUnit, single_metric
from aws_lambda_powertools.metrics.exceptions import (
MetricResolutionError,
MetricUnitError,
MetricValueError,
SchemaValidationError,
)
from .metric import single_metric
from .metrics import EphemeralMetrics, Metrics
from aws_lambda_powertools.metrics.metrics import EphemeralMetrics, Metrics

__all__ = [
"Metrics",
"EphemeralMetrics",
"single_metric",
"MetricUnit",
"MetricUnitError",
"MetricResolution",
"MetricResolutionError",
"SchemaValidationError",
"MetricValueError",
"Metrics",
"EphemeralMetrics",
"MetricResolution",
"MetricUnit",
]
99 changes: 32 additions & 67 deletions aws_lambda_powertools/metrics/base.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import datetime
import functools
import json
Expand All @@ -7,59 +9,28 @@
import warnings
from collections import defaultdict
from contextlib import contextmanager
from enum import Enum
from typing import Any, Callable, Dict, Generator, List, Optional, Union

from ..shared import constants
from ..shared.functions import resolve_env_var_choice
from .exceptions import (
from aws_lambda_powertools.metrics.exceptions import (
MetricResolutionError,
MetricUnitError,
MetricValueError,
SchemaValidationError,
)
from .types import MetricNameUnitResolution
from aws_lambda_powertools.metrics.provider.cloudwatch_emf import cold_start
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.cold_start import (
reset_cold_start_flag, # noqa: F401 # backwards compatibility
)
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.constants import MAX_DIMENSIONS, MAX_METRICS
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.metric_properties import MetricResolution, MetricUnit
from aws_lambda_powertools.metrics.types import MetricNameUnitResolution
from aws_lambda_powertools.shared import constants
from aws_lambda_powertools.shared.functions import resolve_env_var_choice

logger = logging.getLogger(__name__)

MAX_METRICS = 100
MAX_DIMENSIONS = 29

is_cold_start = True


class MetricResolution(Enum):
Standard = 60
High = 1


class MetricUnit(Enum):
Seconds = "Seconds"
Microseconds = "Microseconds"
Milliseconds = "Milliseconds"
Bytes = "Bytes"
Kilobytes = "Kilobytes"
Megabytes = "Megabytes"
Gigabytes = "Gigabytes"
Terabytes = "Terabytes"
Bits = "Bits"
Kilobits = "Kilobits"
Megabits = "Megabits"
Gigabits = "Gigabits"
Terabits = "Terabits"
Percent = "Percent"
Count = "Count"
BytesPerSecond = "Bytes/Second"
KilobytesPerSecond = "Kilobytes/Second"
MegabytesPerSecond = "Megabytes/Second"
GigabytesPerSecond = "Gigabytes/Second"
TerabytesPerSecond = "Terabytes/Second"
BitsPerSecond = "Bits/Second"
KilobitsPerSecond = "Kilobits/Second"
MegabitsPerSecond = "Megabits/Second"
GigabitsPerSecond = "Gigabits/Second"
TerabitsPerSecond = "Terabits/Second"
CountPerSecond = "Count/Second"
# Maintenance: alias due to Hyrum's law
is_cold_start = cold_start.is_cold_start


class MetricManager:
Expand Down Expand Up @@ -94,11 +65,11 @@ class MetricManager:

def __init__(
self,
metric_set: Optional[Dict[str, Any]] = None,
dimension_set: Optional[Dict] = None,
namespace: Optional[str] = None,
metadata_set: Optional[Dict[str, Any]] = None,
service: Optional[str] = None,
metric_set: Dict[str, Any] | None = None,
dimension_set: Dict | None = None,
namespace: str | None = None,
metadata_set: Dict[str, Any] | None = None,
service: str | None = None,
):
self.metric_set = metric_set if metric_set is not None else {}
self.dimension_set = dimension_set if dimension_set is not None else {}
Expand All @@ -112,9 +83,9 @@ def __init__(
def add_metric(
self,
name: str,
unit: Union[MetricUnit, str],
unit: MetricUnit | str,
value: float,
resolution: Union[MetricResolution, int] = 60,
resolution: MetricResolution | int = 60,
) -> None:
"""Adds given metric

Expand Down Expand Up @@ -173,9 +144,9 @@ def add_metric(

def serialize_metric_set(
self,
metrics: Optional[Dict] = None,
dimensions: Optional[Dict] = None,
metadata: Optional[Dict] = None,
metrics: Dict | None = None,
dimensions: Dict | None = None,
metadata: Dict | None = None,
) -> Dict:
"""Serializes metric and dimensions set

Expand Down Expand Up @@ -355,10 +326,10 @@ def flush_metrics(self, raise_on_empty_metrics: bool = False) -> None:

def log_metrics(
self,
lambda_handler: Union[Callable[[Dict, Any], Any], Optional[Callable[[Dict, Any, Optional[Dict]], Any]]] = None,
lambda_handler: Callable[[Dict, Any], Any] | Optional[Callable[[Dict, Any, Optional[Dict]], Any]] = None,
capture_cold_start_metric: bool = False,
raise_on_empty_metrics: bool = False,
default_dimensions: Optional[Dict[str, str]] = None,
default_dimensions: Dict[str, str] | None = None,
):
"""Decorator to serialize and publish metrics at the end of a function execution.

Expand Down Expand Up @@ -537,9 +508,9 @@ class SingleMetric(MetricManager):
def add_metric(
self,
name: str,
unit: Union[MetricUnit, str],
unit: MetricUnit | str,
value: float,
resolution: Union[MetricResolution, int] = 60,
resolution: MetricResolution | int = 60,
) -> None:
"""Method to prevent more than one metric being created

Expand All @@ -565,9 +536,9 @@ def single_metric(
name: str,
unit: MetricUnit,
value: float,
resolution: Union[MetricResolution, int] = 60,
namespace: Optional[str] = None,
default_dimensions: Optional[Dict[str, str]] = None,
resolution: MetricResolution | int = 60,
namespace: str | None = None,
default_dimensions: Dict[str, str] | None = None,
) -> Generator[SingleMetric, None, None]:
"""Context manager to simplify creation of a single metric

Expand Down Expand Up @@ -622,7 +593,7 @@ def single_metric(
SchemaValidationError
When metric object fails EMF schema validation
""" # noqa: E501
metric_set: Optional[Dict] = None
metric_set: Dict | None = None
try:
metric: SingleMetric = SingleMetric(namespace=namespace)
metric.add_metric(name=name, unit=unit, value=value, resolution=resolution)
Expand All @@ -635,9 +606,3 @@ def single_metric(
metric_set = metric.serialize_metric_set()
finally:
print(json.dumps(metric_set, separators=(",", ":")))


def reset_cold_start_flag():
global is_cold_start
if not is_cold_start:
is_cold_start = True
14 changes: 4 additions & 10 deletions aws_lambda_powertools/metrics/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
class MetricUnitError(Exception):
"""When metric unit is not supported by CloudWatch"""

pass


class MetricResolutionError(Exception):
"""When metric resolution is not supported by CloudWatch"""

pass
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.exceptions import MetricResolutionError, MetricUnitError


class SchemaValidationError(Exception):
Expand All @@ -20,3 +11,6 @@ class MetricValueError(Exception):
"""When metric value isn't a valid number"""

pass


__all__ = ["MetricUnitError", "MetricResolutionError", "SchemaValidationError", "MetricValueError"]
2 changes: 1 addition & 1 deletion aws_lambda_powertools/metrics/metric.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# NOTE: prevents circular inheritance import
from .base import SingleMetric, single_metric
from aws_lambda_powertools.metrics.base import SingleMetric, single_metric

__all__ = ["SingleMetric", "single_metric"]
Loading