Skip to content

docs(metrics): snippets split, improved, and lint #1272

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

Merged
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
347 changes: 91 additions & 256 deletions docs/core/metrics.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/core/tracer.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ You can trace asynchronous functions and generator functions (including context

=== "Async"

```python hl_lines="8"
```python hl_lines="9"
--8<-- "examples/tracer/src/capture_method_async.py"
```

Expand Down
25 changes: 25 additions & 0 deletions examples/metrics/sam/template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: AWS Lambda Powertools Metrics doc examples

Globals:
Function:
Timeout: 5
Runtime: python3.9
Tracing: Active
Environment:
Variables:
POWERTOOLS_SERVICE_NAME: booking
POWERTOOLS_METRICS_NAMESPACE: ServerlessAirline

Layers:
# Find the latest Layer version in the official documentation
# https://awslabs.github.io/aws-lambda-powertools-python/latest/#lambda-layer
- !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPython:21

Resources:
CaptureLambdaHandlerExample:
Type: AWS::Serverless::Function
Properties:
CodeUri: ../src
Handler: capture_lambda_handler.handler
14 changes: 14 additions & 0 deletions examples/metrics/src/add_dimension.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import os

from aws_lambda_powertools import Metrics
from aws_lambda_powertools.metrics import MetricUnit
from aws_lambda_powertools.utilities.typing import LambdaContext

STAGE = os.getenv("STAGE", "dev")
metrics = Metrics()


@metrics.log_metrics # ensures metrics are flushed upon request completion/failure
def lambda_handler(event: dict, context: LambdaContext):
metrics.add_dimension(name="environment", value=STAGE)
metrics.add_metric(name="SuccessfulBooking", unit=MetricUnit.Count, value=1)
13 changes: 13 additions & 0 deletions examples/metrics/src/add_metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from uuid import uuid4

from aws_lambda_powertools import Metrics
from aws_lambda_powertools.metrics import MetricUnit
from aws_lambda_powertools.utilities.typing import LambdaContext

metrics = Metrics()


@metrics.log_metrics
def lambda_handler(event: dict, context: LambdaContext):
metrics.add_metric(name="SuccessfulBooking", unit=MetricUnit.Count, value=1)
metrics.add_metadata(key="booking_id", value=f"{uuid4()}")
26 changes: 26 additions & 0 deletions examples/metrics/src/add_metadata_output.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"_aws": {
"Timestamp": 1656688250155,
"CloudWatchMetrics": [
{
"Namespace": "ServerlessAirline",
"Dimensions": [
[
"service"
]
],
"Metrics": [
{
"Name": "SuccessfulBooking",
"Unit": "Count"
}
]
}
]
},
"service": "booking",
"booking_id": "00347014-341d-4b8e-8421-a89d3d588ab3",
"SuccessfulBooking": [
1.0
]
}
10 changes: 10 additions & 0 deletions examples/metrics/src/add_metrics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from aws_lambda_powertools import Metrics
from aws_lambda_powertools.metrics import MetricUnit
from aws_lambda_powertools.utilities.typing import LambdaContext

metrics = Metrics()


@metrics.log_metrics # ensures metrics are flushed upon request completion/failure
def lambda_handler(event: dict, context: LambdaContext):
metrics.add_metric(name="SuccessfulBooking", unit=MetricUnit.Count, value=1)
15 changes: 15 additions & 0 deletions examples/metrics/src/add_multi_value_metrics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import os

from aws_lambda_powertools import Metrics
from aws_lambda_powertools.metrics import MetricUnit
from aws_lambda_powertools.utilities.typing import LambdaContext

STAGE = os.getenv("STAGE", "dev")
metrics = Metrics()


@metrics.log_metrics # ensures metrics are flushed upon request completion/failure
def lambda_handler(event: dict, context: LambdaContext):
metrics.add_dimension(name="environment", value=STAGE)
metrics.add_metric(name="TurbineReads", unit=MetricUnit.Count, value=1)
metrics.add_metric(name="TurbineReads", unit=MetricUnit.Count, value=8)
28 changes: 28 additions & 0 deletions examples/metrics/src/add_multi_value_metrics_output.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"_aws": {
"Timestamp": 1656685750622,
"CloudWatchMetrics": [
{
"Namespace": "ServerlessAirline",
"Dimensions": [
[
"environment",
"service"
]
],
"Metrics": [
{
"Name": "TurbineReads",
"Unit": "Count"
}
]
}
]
},
"environment": "dev",
"service": "booking",
"TurbineReads": [
1.0,
8.0
]
}
34 changes: 34 additions & 0 deletions examples/metrics/src/assert_multiple_emf_blobs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import json
from dataclasses import dataclass

import assert_multiple_emf_blobs_module
import pytest


@pytest.fixture
def lambda_context():
@dataclass
class LambdaContext:
function_name: str = "test"
memory_limit_in_mb: int = 128
invoked_function_arn: str = "arn:aws:lambda:eu-west-1:809313241:function:test"
aws_request_id: str = "52fdfc07-2182-154f-163f-5f0f9a621d72"

return LambdaContext()


def capture_metrics_output_multiple_emf_objects(capsys):
return [json.loads(line.strip()) for line in capsys.readouterr().out.split("\n") if line]


def test_log_metrics(capsys, lambda_context):
assert_multiple_emf_blobs_module.lambda_handler({}, lambda_context)

cold_start_blob, custom_metrics_blob = capture_metrics_output_multiple_emf_objects(capsys)

# Since `capture_cold_start_metric` is used
# we should have one JSON blob for cold start metric and one for the application
assert cold_start_blob["ColdStart"] == [1.0]
assert cold_start_blob["function_name"] == "test"

assert "SuccessfulBooking" in custom_metrics_blob
10 changes: 10 additions & 0 deletions examples/metrics/src/assert_multiple_emf_blobs_module.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from aws_lambda_powertools import Metrics
from aws_lambda_powertools.metrics import MetricUnit
from aws_lambda_powertools.utilities.typing import LambdaContext

metrics = Metrics()


@metrics.log_metrics(capture_cold_start_metric=True)
def lambda_handler(event: dict, context: LambdaContext):
metrics.add_metric(name="SuccessfulBooking", unit=MetricUnit.Count, value=1)
15 changes: 15 additions & 0 deletions examples/metrics/src/assert_single_emf_blob.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import json

import add_metrics


def test_log_metrics(capsys):
add_metrics.lambda_handler({}, {})

log = capsys.readouterr().out.strip() # remove any extra line
metrics_output = json.loads(log) # deserialize JSON str

# THEN we should have no exceptions
# and a valid EMF object should be flushed correctly
assert "SuccessfulBooking" in log # basic string assertion in JSON str
assert "SuccessfulBooking" in metrics_output["_aws"]["CloudWatchMetrics"][0]["Metrics"][0]["Name"]
9 changes: 9 additions & 0 deletions examples/metrics/src/capture_cold_start_metric.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from aws_lambda_powertools import Metrics
from aws_lambda_powertools.utilities.typing import LambdaContext

metrics = Metrics()


@metrics.log_metrics(capture_cold_start_metric=True)
def lambda_handler(event: dict, context: LambdaContext):
...
27 changes: 27 additions & 0 deletions examples/metrics/src/capture_cold_start_metric_output.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"_aws": {
"Timestamp": 1656687493142,
"CloudWatchMetrics": [
{
"Namespace": "ServerlessAirline",
"Dimensions": [
[
"function_name",
"service"
]
],
"Metrics": [
{
"Name": "ColdStart",
"Unit": "Count"
}
]
}
]
},
"function_name": "test",
"service": "booking",
"ColdStart": [
1.0
]
}
14 changes: 14 additions & 0 deletions examples/metrics/src/clear_metrics_in_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import pytest

from aws_lambda_powertools import Metrics
from aws_lambda_powertools.metrics import metrics as metrics_global


@pytest.fixture(scope="function", autouse=True)
def reset_metric_set():
# Clear out every metric data prior to every test
metrics = Metrics()
metrics.clear_metrics()
metrics_global.is_cold_start = True # ensure each test has cold start
metrics.clear_default_dimensions() # remove persisted default dimensions, if any
yield
25 changes: 25 additions & 0 deletions examples/metrics/src/log_metrics_output.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"_aws": {
"Timestamp": 1656686788803,
"CloudWatchMetrics": [
{
"Namespace": "ServerlessAirline",
"Dimensions": [
[
"service"
]
],
"Metrics": [
{
"Name": "SuccessfulBooking",
"Unit": "Count"
}
]
}
]
},
"service": "booking",
"SuccessfulBooking": [
1.0
]
}
14 changes: 14 additions & 0 deletions examples/metrics/src/manual_flush.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import json

from aws_lambda_powertools import Metrics
from aws_lambda_powertools.metrics import MetricUnit
from aws_lambda_powertools.utilities.typing import LambdaContext

metrics = Metrics()


def lambda_handler(event: dict, context: LambdaContext):
metrics.add_metric(name="SuccessfulBooking", unit=MetricUnit.Count, value=1)
your_metrics_object = metrics.serialize_metric_set()
metrics.clear_metrics()
print(json.dumps(your_metrics_object))
10 changes: 10 additions & 0 deletions examples/metrics/src/raise_on_empty_metrics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from aws_lambda_powertools.metrics import Metrics
from aws_lambda_powertools.utilities.typing import LambdaContext

metrics = Metrics()


@metrics.log_metrics(raise_on_empty_metrics=True)
def lambda_handler(event: dict, context: LambdaContext):
# no metrics being created will now raise SchemaValidationError
...
1 change: 1 addition & 0 deletions examples/metrics/src/run_tests_env_var.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
POWERTOOLS_SERVICE_NAME="booking" POWERTOOLS_METRICS_NAMESPACE="ServerlessAirline" python -m pytest
15 changes: 15 additions & 0 deletions examples/metrics/src/set_default_dimensions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import os

from aws_lambda_powertools import Metrics
from aws_lambda_powertools.metrics import MetricUnit
from aws_lambda_powertools.utilities.typing import LambdaContext

STAGE = os.getenv("STAGE", "dev")
metrics = Metrics()
metrics.set_default_dimensions(environment=STAGE, another="one")


@metrics.log_metrics # ensures metrics are flushed upon request completion/failure
def lambda_handler(event: dict, context: LambdaContext):
metrics.add_metric(name="TurbineReads", unit=MetricUnit.Count, value=1)
metrics.add_metric(name="TurbineReads", unit=MetricUnit.Count, value=8)
16 changes: 16 additions & 0 deletions examples/metrics/src/set_default_dimensions_log_metrics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import os

from aws_lambda_powertools import Metrics
from aws_lambda_powertools.metrics import MetricUnit
from aws_lambda_powertools.utilities.typing import LambdaContext

STAGE = os.getenv("STAGE", "dev")
metrics = Metrics()
DEFAULT_DIMENSIONS = {"environment": STAGE, "another": "one"}


# ensures metrics are flushed upon request completion/failure
@metrics.log_metrics(default_dimensions=DEFAULT_DIMENSIONS)
def lambda_handler(event: dict, context: LambdaContext):
metrics.add_metric(name="TurbineReads", unit=MetricUnit.Count, value=1)
metrics.add_metric(name="TurbineReads", unit=MetricUnit.Count, value=8)
12 changes: 12 additions & 0 deletions examples/metrics/src/single_metric.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import os

from aws_lambda_powertools import single_metric
from aws_lambda_powertools.metrics import MetricUnit
from aws_lambda_powertools.utilities.typing import LambdaContext

STAGE = os.getenv("STAGE", "dev")


def lambda_handler(event: dict, context: LambdaContext):
with single_metric(name="MySingleMetric", unit=MetricUnit.Count, value=1) as metric:
metric.add_dimension(name="environment", value=STAGE)
27 changes: 27 additions & 0 deletions examples/metrics/src/single_metric_output.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"_aws": {
"Timestamp": 1656689267834,
"CloudWatchMetrics": [
{
"Namespace": "ServerlessAirline",
"Dimensions": [
[
"environment",
"service"
]
],
"Metrics": [
{
"Name": "MySingleMetric",
"Unit": "Count"
}
]
}
]
},
"environment": "dev",
"service": "booking",
"MySingleMetric": [
1.0
]
}
2 changes: 1 addition & 1 deletion examples/tracer/sam/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Globals:
Tracing: Active
Environment:
Variables:
POWERTOOLS_SERVICE_NAME: example
POWERTOOLS_SERVICE_NAME: payment
Layers:
# Find the latest Layer version in the official documentation
# https://awslabs.github.io/aws-lambda-powertools-python/latest/#lambda-layer
Expand Down