Skip to content

Commit c8ae0d5

Browse files
authored
docs(metrics): snippets split, improved, and lint (#1272)
1 parent e8f9ad1 commit c8ae0d5

24 files changed

+453
-258
lines changed

docs/core/metrics.md

Lines changed: 91 additions & 256 deletions
Large diffs are not rendered by default.

docs/core/tracer.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ You can trace asynchronous functions and generator functions (including context
7676

7777
=== "Async"
7878

79-
```python hl_lines="8"
79+
```python hl_lines="9"
8080
--8<-- "examples/tracer/src/capture_method_async.py"
8181
```
8282

examples/metrics/sam/template.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
AWSTemplateFormatVersion: "2010-09-09"
2+
Transform: AWS::Serverless-2016-10-31
3+
Description: AWS Lambda Powertools Metrics doc examples
4+
5+
Globals:
6+
Function:
7+
Timeout: 5
8+
Runtime: python3.9
9+
Tracing: Active
10+
Environment:
11+
Variables:
12+
POWERTOOLS_SERVICE_NAME: booking
13+
POWERTOOLS_METRICS_NAMESPACE: ServerlessAirline
14+
15+
Layers:
16+
# Find the latest Layer version in the official documentation
17+
# https://awslabs.github.io/aws-lambda-powertools-python/latest/#lambda-layer
18+
- !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPython:21
19+
20+
Resources:
21+
CaptureLambdaHandlerExample:
22+
Type: AWS::Serverless::Function
23+
Properties:
24+
CodeUri: ../src
25+
Handler: capture_lambda_handler.handler

examples/metrics/src/add_dimension.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import os
2+
3+
from aws_lambda_powertools import Metrics
4+
from aws_lambda_powertools.metrics import MetricUnit
5+
from aws_lambda_powertools.utilities.typing import LambdaContext
6+
7+
STAGE = os.getenv("STAGE", "dev")
8+
metrics = Metrics()
9+
10+
11+
@metrics.log_metrics # ensures metrics are flushed upon request completion/failure
12+
def lambda_handler(event: dict, context: LambdaContext):
13+
metrics.add_dimension(name="environment", value=STAGE)
14+
metrics.add_metric(name="SuccessfulBooking", unit=MetricUnit.Count, value=1)

examples/metrics/src/add_metadata.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from uuid import uuid4
2+
3+
from aws_lambda_powertools import Metrics
4+
from aws_lambda_powertools.metrics import MetricUnit
5+
from aws_lambda_powertools.utilities.typing import LambdaContext
6+
7+
metrics = Metrics()
8+
9+
10+
@metrics.log_metrics
11+
def lambda_handler(event: dict, context: LambdaContext):
12+
metrics.add_metric(name="SuccessfulBooking", unit=MetricUnit.Count, value=1)
13+
metrics.add_metadata(key="booking_id", value=f"{uuid4()}")
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"_aws": {
3+
"Timestamp": 1656688250155,
4+
"CloudWatchMetrics": [
5+
{
6+
"Namespace": "ServerlessAirline",
7+
"Dimensions": [
8+
[
9+
"service"
10+
]
11+
],
12+
"Metrics": [
13+
{
14+
"Name": "SuccessfulBooking",
15+
"Unit": "Count"
16+
}
17+
]
18+
}
19+
]
20+
},
21+
"service": "booking",
22+
"booking_id": "00347014-341d-4b8e-8421-a89d3d588ab3",
23+
"SuccessfulBooking": [
24+
1.0
25+
]
26+
}

examples/metrics/src/add_metrics.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from aws_lambda_powertools import Metrics
2+
from aws_lambda_powertools.metrics import MetricUnit
3+
from aws_lambda_powertools.utilities.typing import LambdaContext
4+
5+
metrics = Metrics()
6+
7+
8+
@metrics.log_metrics # ensures metrics are flushed upon request completion/failure
9+
def lambda_handler(event: dict, context: LambdaContext):
10+
metrics.add_metric(name="SuccessfulBooking", unit=MetricUnit.Count, value=1)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import os
2+
3+
from aws_lambda_powertools import Metrics
4+
from aws_lambda_powertools.metrics import MetricUnit
5+
from aws_lambda_powertools.utilities.typing import LambdaContext
6+
7+
STAGE = os.getenv("STAGE", "dev")
8+
metrics = Metrics()
9+
10+
11+
@metrics.log_metrics # ensures metrics are flushed upon request completion/failure
12+
def lambda_handler(event: dict, context: LambdaContext):
13+
metrics.add_dimension(name="environment", value=STAGE)
14+
metrics.add_metric(name="TurbineReads", unit=MetricUnit.Count, value=1)
15+
metrics.add_metric(name="TurbineReads", unit=MetricUnit.Count, value=8)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"_aws": {
3+
"Timestamp": 1656685750622,
4+
"CloudWatchMetrics": [
5+
{
6+
"Namespace": "ServerlessAirline",
7+
"Dimensions": [
8+
[
9+
"environment",
10+
"service"
11+
]
12+
],
13+
"Metrics": [
14+
{
15+
"Name": "TurbineReads",
16+
"Unit": "Count"
17+
}
18+
]
19+
}
20+
]
21+
},
22+
"environment": "dev",
23+
"service": "booking",
24+
"TurbineReads": [
25+
1.0,
26+
8.0
27+
]
28+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import json
2+
from dataclasses import dataclass
3+
4+
import assert_multiple_emf_blobs_module
5+
import pytest
6+
7+
8+
@pytest.fixture
9+
def lambda_context():
10+
@dataclass
11+
class LambdaContext:
12+
function_name: str = "test"
13+
memory_limit_in_mb: int = 128
14+
invoked_function_arn: str = "arn:aws:lambda:eu-west-1:809313241:function:test"
15+
aws_request_id: str = "52fdfc07-2182-154f-163f-5f0f9a621d72"
16+
17+
return LambdaContext()
18+
19+
20+
def capture_metrics_output_multiple_emf_objects(capsys):
21+
return [json.loads(line.strip()) for line in capsys.readouterr().out.split("\n") if line]
22+
23+
24+
def test_log_metrics(capsys, lambda_context):
25+
assert_multiple_emf_blobs_module.lambda_handler({}, lambda_context)
26+
27+
cold_start_blob, custom_metrics_blob = capture_metrics_output_multiple_emf_objects(capsys)
28+
29+
# Since `capture_cold_start_metric` is used
30+
# we should have one JSON blob for cold start metric and one for the application
31+
assert cold_start_blob["ColdStart"] == [1.0]
32+
assert cold_start_blob["function_name"] == "test"
33+
34+
assert "SuccessfulBooking" in custom_metrics_blob
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from aws_lambda_powertools import Metrics
2+
from aws_lambda_powertools.metrics import MetricUnit
3+
from aws_lambda_powertools.utilities.typing import LambdaContext
4+
5+
metrics = Metrics()
6+
7+
8+
@metrics.log_metrics(capture_cold_start_metric=True)
9+
def lambda_handler(event: dict, context: LambdaContext):
10+
metrics.add_metric(name="SuccessfulBooking", unit=MetricUnit.Count, value=1)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import json
2+
3+
import add_metrics
4+
5+
6+
def test_log_metrics(capsys):
7+
add_metrics.lambda_handler({}, {})
8+
9+
log = capsys.readouterr().out.strip() # remove any extra line
10+
metrics_output = json.loads(log) # deserialize JSON str
11+
12+
# THEN we should have no exceptions
13+
# and a valid EMF object should be flushed correctly
14+
assert "SuccessfulBooking" in log # basic string assertion in JSON str
15+
assert "SuccessfulBooking" in metrics_output["_aws"]["CloudWatchMetrics"][0]["Metrics"][0]["Name"]
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from aws_lambda_powertools import Metrics
2+
from aws_lambda_powertools.utilities.typing import LambdaContext
3+
4+
metrics = Metrics()
5+
6+
7+
@metrics.log_metrics(capture_cold_start_metric=True)
8+
def lambda_handler(event: dict, context: LambdaContext):
9+
...
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"_aws": {
3+
"Timestamp": 1656687493142,
4+
"CloudWatchMetrics": [
5+
{
6+
"Namespace": "ServerlessAirline",
7+
"Dimensions": [
8+
[
9+
"function_name",
10+
"service"
11+
]
12+
],
13+
"Metrics": [
14+
{
15+
"Name": "ColdStart",
16+
"Unit": "Count"
17+
}
18+
]
19+
}
20+
]
21+
},
22+
"function_name": "test",
23+
"service": "booking",
24+
"ColdStart": [
25+
1.0
26+
]
27+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import pytest
2+
3+
from aws_lambda_powertools import Metrics
4+
from aws_lambda_powertools.metrics import metrics as metrics_global
5+
6+
7+
@pytest.fixture(scope="function", autouse=True)
8+
def reset_metric_set():
9+
# Clear out every metric data prior to every test
10+
metrics = Metrics()
11+
metrics.clear_metrics()
12+
metrics_global.is_cold_start = True # ensure each test has cold start
13+
metrics.clear_default_dimensions() # remove persisted default dimensions, if any
14+
yield
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"_aws": {
3+
"Timestamp": 1656686788803,
4+
"CloudWatchMetrics": [
5+
{
6+
"Namespace": "ServerlessAirline",
7+
"Dimensions": [
8+
[
9+
"service"
10+
]
11+
],
12+
"Metrics": [
13+
{
14+
"Name": "SuccessfulBooking",
15+
"Unit": "Count"
16+
}
17+
]
18+
}
19+
]
20+
},
21+
"service": "booking",
22+
"SuccessfulBooking": [
23+
1.0
24+
]
25+
}

examples/metrics/src/manual_flush.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import json
2+
3+
from aws_lambda_powertools import Metrics
4+
from aws_lambda_powertools.metrics import MetricUnit
5+
from aws_lambda_powertools.utilities.typing import LambdaContext
6+
7+
metrics = Metrics()
8+
9+
10+
def lambda_handler(event: dict, context: LambdaContext):
11+
metrics.add_metric(name="SuccessfulBooking", unit=MetricUnit.Count, value=1)
12+
your_metrics_object = metrics.serialize_metric_set()
13+
metrics.clear_metrics()
14+
print(json.dumps(your_metrics_object))
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from aws_lambda_powertools.metrics import Metrics
2+
from aws_lambda_powertools.utilities.typing import LambdaContext
3+
4+
metrics = Metrics()
5+
6+
7+
@metrics.log_metrics(raise_on_empty_metrics=True)
8+
def lambda_handler(event: dict, context: LambdaContext):
9+
# no metrics being created will now raise SchemaValidationError
10+
...
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
POWERTOOLS_SERVICE_NAME="booking" POWERTOOLS_METRICS_NAMESPACE="ServerlessAirline" python -m pytest
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import os
2+
3+
from aws_lambda_powertools import Metrics
4+
from aws_lambda_powertools.metrics import MetricUnit
5+
from aws_lambda_powertools.utilities.typing import LambdaContext
6+
7+
STAGE = os.getenv("STAGE", "dev")
8+
metrics = Metrics()
9+
metrics.set_default_dimensions(environment=STAGE, another="one")
10+
11+
12+
@metrics.log_metrics # ensures metrics are flushed upon request completion/failure
13+
def lambda_handler(event: dict, context: LambdaContext):
14+
metrics.add_metric(name="TurbineReads", unit=MetricUnit.Count, value=1)
15+
metrics.add_metric(name="TurbineReads", unit=MetricUnit.Count, value=8)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import os
2+
3+
from aws_lambda_powertools import Metrics
4+
from aws_lambda_powertools.metrics import MetricUnit
5+
from aws_lambda_powertools.utilities.typing import LambdaContext
6+
7+
STAGE = os.getenv("STAGE", "dev")
8+
metrics = Metrics()
9+
DEFAULT_DIMENSIONS = {"environment": STAGE, "another": "one"}
10+
11+
12+
# ensures metrics are flushed upon request completion/failure
13+
@metrics.log_metrics(default_dimensions=DEFAULT_DIMENSIONS)
14+
def lambda_handler(event: dict, context: LambdaContext):
15+
metrics.add_metric(name="TurbineReads", unit=MetricUnit.Count, value=1)
16+
metrics.add_metric(name="TurbineReads", unit=MetricUnit.Count, value=8)

examples/metrics/src/single_metric.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import os
2+
3+
from aws_lambda_powertools import single_metric
4+
from aws_lambda_powertools.metrics import MetricUnit
5+
from aws_lambda_powertools.utilities.typing import LambdaContext
6+
7+
STAGE = os.getenv("STAGE", "dev")
8+
9+
10+
def lambda_handler(event: dict, context: LambdaContext):
11+
with single_metric(name="MySingleMetric", unit=MetricUnit.Count, value=1) as metric:
12+
metric.add_dimension(name="environment", value=STAGE)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"_aws": {
3+
"Timestamp": 1656689267834,
4+
"CloudWatchMetrics": [
5+
{
6+
"Namespace": "ServerlessAirline",
7+
"Dimensions": [
8+
[
9+
"environment",
10+
"service"
11+
]
12+
],
13+
"Metrics": [
14+
{
15+
"Name": "MySingleMetric",
16+
"Unit": "Count"
17+
}
18+
]
19+
}
20+
]
21+
},
22+
"environment": "dev",
23+
"service": "booking",
24+
"MySingleMetric": [
25+
1.0
26+
]
27+
}

examples/tracer/sam/template.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Globals:
99
Tracing: Active
1010
Environment:
1111
Variables:
12-
POWERTOOLS_SERVICE_NAME: example
12+
POWERTOOLS_SERVICE_NAME: payment
1313
Layers:
1414
# Find the latest Layer version in the official documentation
1515
# https://awslabs.github.io/aws-lambda-powertools-python/latest/#lambda-layer

0 commit comments

Comments
 (0)