Skip to content

Commit 2a51de0

Browse files
committed
docs(event-handler): snippets split, improved, and lint (#1279)
1 parent 3927738 commit 2a51de0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1164
-1018
lines changed

docs/core/event_handler/api_gateway.md

+148-1,018
Large diffs are not rendered by default.

docs/core/logger.md

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ Logger provides an opinionated logger with output structured as JSON.
1414

1515
## Getting started
1616

17+
???+ tip
18+
All examples shared in this documentation are available within the [project repository](https://github.com/awslabs/aws-lambda-powertools-python/tree/develop/examples){target="_blank"}.
19+
1720
Logger requires two settings:
1821

1922
| Setting | Description | Environment variable | Constructor parameter |

docs/core/metrics.md

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ If you're new to Amazon CloudWatch, there are two terminologies you must be awar
2828

2929
## Getting started
3030

31+
???+ tip
32+
All examples shared in this documentation are available within the [project repository](https://github.com/awslabs/aws-lambda-powertools-python/tree/develop/examples){target="_blank"}.
33+
3134
Metric has two global settings that will be used across all metrics emitted:
3235

3336
| Setting | Description | Environment variable | Constructor parameter |

docs/core/tracer.md

+3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ Tracer is an opinionated thin wrapper for [AWS X-Ray Python SDK](https://github.
1616

1717
## Getting started
1818

19+
???+ tip
20+
All examples shared in this documentation are available within the [project repository](https://github.com/awslabs/aws-lambda-powertools-python/tree/develop/examples){target="_blank"}.
21+
1922
### Permissions
2023

2124
Before your use this utility, your AWS Lambda function [must have permissions](https://docs.aws.amazon.com/lambda/latest/dg/services-xray.html#services-xray-permissions) to send traces to AWS X-Ray.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
AWSTemplateFormatVersion: "2010-09-09"
2+
Transform: AWS::Serverless-2016-10-31
3+
Description: Hello world event handler API Gateway
4+
5+
Globals:
6+
Api:
7+
TracingEnabled: true
8+
Cors: # see CORS section
9+
AllowOrigin: "'https://example.com'"
10+
AllowHeaders: "'Content-Type,Authorization,X-Amz-Date'"
11+
MaxAge: "'300'"
12+
BinaryMediaTypes: # see Binary responses section
13+
- "*~1*" # converts to */* for any binary type
14+
Function:
15+
Timeout: 5
16+
Runtime: python3.8
17+
Tracing: Active
18+
Environment:
19+
Variables:
20+
LOG_LEVEL: INFO
21+
POWERTOOLS_LOGGER_SAMPLE_RATE: 0.1
22+
POWERTOOLS_LOGGER_LOG_EVENT: true
23+
POWERTOOLS_SERVICE_NAME: example
24+
25+
Resources:
26+
ApiFunction:
27+
Type: AWS::Serverless::Function
28+
Properties:
29+
Handler: app.lambda_handler
30+
CodeUri: api_handler/
31+
Description: API handler function
32+
Events:
33+
AnyApiEvent:
34+
Type: Api
35+
Properties:
36+
# NOTE: this is a catch-all rule to simplify the documentation.
37+
# explicit routes and methods are recommended for prod instead (see below)
38+
Path: /{proxy+} # Send requests on any path to the lambda function
39+
Method: ANY # Send requests using any http method to the lambda function
40+
41+
42+
# GetAllTodos:
43+
# Type: Api
44+
# Properties:
45+
# Path: /todos
46+
# Method: GET
47+
# GetTodoById:
48+
# Type: Api
49+
# Properties:
50+
# Path: /todos/{todo_id}
51+
# Method: GET
52+
# CreateTodo:
53+
# Type: Api
54+
# Properties:
55+
# Path: /todos
56+
# Method: POST
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from typing import Optional
2+
3+
import requests
4+
from requests import Response
5+
6+
from aws_lambda_powertools import Logger, Tracer
7+
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
8+
from aws_lambda_powertools.logging import correlation_paths
9+
from aws_lambda_powertools.utilities.typing import LambdaContext
10+
11+
tracer = Tracer()
12+
logger = Logger()
13+
app = APIGatewayRestResolver()
14+
15+
16+
@app.get("/todos")
17+
@tracer.capture_method
18+
def get_todos():
19+
todo_id: str = app.current_event.get_query_string_value(name="id", default_value="")
20+
# alternatively
21+
_: Optional[str] = app.current_event.query_string_parameters.get("id")
22+
23+
# Payload
24+
_: Optional[str] = app.current_event.body # raw str | None
25+
26+
endpoint = "https://jsonplaceholder.typicode.com/todos"
27+
if todo_id:
28+
endpoint = f"{endpoint}/{todo_id}"
29+
30+
todos: Response = requests.get(endpoint)
31+
todos.raise_for_status()
32+
33+
return {"todos": todos.json()}
34+
35+
36+
# You can continue to use other utilities just as before
37+
@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST)
38+
@tracer.capture_lambda_handler
39+
def lambda_handler(event: dict, context: LambdaContext) -> dict:
40+
return app.resolve(event, context)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import requests
2+
from requests import Response
3+
4+
from aws_lambda_powertools import Logger, Tracer
5+
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
6+
from aws_lambda_powertools.logging import correlation_paths
7+
from aws_lambda_powertools.utilities.typing import LambdaContext
8+
9+
tracer = Tracer()
10+
logger = Logger()
11+
app = APIGatewayRestResolver()
12+
13+
14+
@app.get("/todos")
15+
@tracer.capture_method
16+
def get_todos():
17+
endpoint = "https://jsonplaceholder.typicode.com/todos"
18+
19+
api_key: str = app.current_event.get_header_value(name="X-Api-Key", case_sensitive=True, default_value="")
20+
todos: Response = requests.get(endpoint, headers={"X-Api-Key": api_key})
21+
todos.raise_for_status()
22+
23+
return {"todos": todos.json()}
24+
25+
26+
# You can continue to use other utilities just as before
27+
@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST)
28+
@tracer.capture_lambda_handler
29+
def lambda_handler(event: dict, context: LambdaContext) -> dict:
30+
return app.resolve(event, context)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from dataclasses import dataclass
2+
3+
import assert_http_response_module
4+
import pytest
5+
6+
7+
@pytest.fixture
8+
def lambda_context():
9+
@dataclass
10+
class LambdaContext:
11+
function_name: str = "test"
12+
memory_limit_in_mb: int = 128
13+
invoked_function_arn: str = "arn:aws:lambda:eu-west-1:123456789012:function:test"
14+
aws_request_id: str = "da658bd3-2d6f-4e7b-8ec2-937234644fdc"
15+
16+
return LambdaContext()
17+
18+
19+
def test_lambda_handler(lambda_context):
20+
minimal_event = {
21+
"path": "/todos",
22+
"httpMethod": "GET",
23+
"requestContext": {"requestId": "227b78aa-779d-47d4-a48e-ce62120393b8"}, # correlation ID
24+
}
25+
26+
ret = assert_http_response_module.lambda_handler(minimal_event, lambda_context)
27+
assert ret["statusCode"] == 200
28+
assert ret["body"] != ""
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import requests
2+
from requests import Response
3+
4+
from aws_lambda_powertools import Logger, Tracer
5+
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
6+
from aws_lambda_powertools.logging import correlation_paths
7+
from aws_lambda_powertools.utilities.typing import LambdaContext
8+
9+
tracer = Tracer()
10+
logger = Logger()
11+
app = APIGatewayRestResolver()
12+
13+
14+
@app.get("/todos")
15+
@tracer.capture_method
16+
def get_todos():
17+
todos: Response = requests.get("https://jsonplaceholder.typicode.com/todos")
18+
todos.raise_for_status()
19+
20+
return {"todos": todos.json()[:10]}
21+
22+
23+
# You can continue to use other utilities just as before
24+
@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST)
25+
@tracer.capture_lambda_handler
26+
def lambda_handler(event: dict, context: LambdaContext) -> dict:
27+
return app.resolve(event, context)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"headers": {
3+
"Accept": "image/svg+xml"
4+
},
5+
"resource": "/logo",
6+
"path": "/logo",
7+
"httpMethod": "GET"
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import os
2+
from pathlib import Path
3+
4+
from aws_lambda_powertools import Logger, Tracer
5+
from aws_lambda_powertools.event_handler.api_gateway import APIGatewayRestResolver, Response
6+
from aws_lambda_powertools.logging import correlation_paths
7+
from aws_lambda_powertools.utilities.typing import LambdaContext
8+
9+
tracer = Tracer()
10+
logger = Logger()
11+
12+
13+
app = APIGatewayRestResolver()
14+
logo_file: bytes = Path(os.getenv("LAMBDA_TASK_ROOT") + "/logo.svg").read_bytes()
15+
16+
17+
@app.get("/logo")
18+
@tracer.capture_method
19+
def get_logo():
20+
return Response(status_code=200, content_type="image/svg+xml", body=logo_file)
21+
22+
23+
# You can continue to use other utilities just as before
24+
@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST)
25+
@tracer.capture_lambda_handler
26+
def lambda_handler(event: dict, context: LambdaContext) -> dict:
27+
return app.resolve(event, context)
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"body": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMjU2cHgiIGhlaWdodD0iMjU2cHgiIHZpZXdCb3g9IjAgMCAyNTYgMjU2IiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIj4KICAgIDx0aXRsZT5BV1MgTGFtYmRhPC90aXRsZT4KICAgIDxkZWZzPgogICAgICAgIDxsaW5lYXJHcmFkaWVudCB4MT0iMCUiIHkxPSIxMDAlIiB4Mj0iMTAwJSIgeTI9IjAlIiBpZD0ibGluZWFyR3JhZGllbnQtMSI+CiAgICAgICAgICAgIDxzdG9wIHN0b3AtY29sb3I9IiNDODUxMUIiIG9mZnNldD0iMCUiPjwvc3RvcD4KICAgICAgICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iI0ZGOTkwMCIgb2Zmc2V0PSIxMDAlIj48L3N0b3A+CiAgICAgICAgPC9saW5lYXJHcmFkaWVudD4KICAgIDwvZGVmcz4KICAgIDxnPgogICAgICAgIDxyZWN0IGZpbGw9InVybCgjbGluZWFyR3JhZGllbnQtMSkiIHg9IjAiIHk9IjAiIHdpZHRoPSIyNTYiIGhlaWdodD0iMjU2Ij48L3JlY3Q+CiAgICAgICAgPHBhdGggZD0iTTg5LjYyNDExMjYsMjExLjIgTDQ5Ljg5MDMyNzcsMjExLjIgTDkzLjgzNTQ4MzIsMTE5LjM0NzIgTDExMy43NDcyOCwxNjAuMzM5MiBMODkuNjI0MTEyNiwyMTEuMiBaIE05Ni43MDI5MzU3LDExMC41Njk2IEM5Ni4xNjQwODU4LDEwOS40NjU2IDk1LjA0MTQ4MTMsMTA4Ljc2NDggOTMuODE2MjM4NCwxMDguNzY0OCBMOTMuODA2NjE2MywxMDguNzY0OCBDOTIuNTcxNzUxNCwxMDguNzY4IDkxLjQ0OTE0NjYsMTA5LjQ3NTIgOTAuOTE5OTE4NywxMTAuNTg1NiBMNDEuOTEzNDIwOCwyMTMuMDIwOCBDNDEuNDM4NzE5NywyMTQuMDEyOCA0MS41MDYwNzU4LDIxNS4xNzc2IDQyLjA5NjI0NTEsMjE2LjEwODggQzQyLjY3OTk5OTQsMjE3LjAzNjggNDMuNzA2MzgwNSwyMTcuNiA0NC44MDY1MzMxLDIxNy42IEw5MS42NTQ0MjMsMjE3LjYgQzkyLjg5NTcwMjcsMjE3LjYgOTQuMDIxNTE0OSwyMTYuODg2NCA5NC41NTM5NTAxLDIxNS43Njk2IEwxMjAuMjAzODU5LDE2MS42ODk2IEMxMjAuNjE3NjE5LDE2MC44MTI4IDEyMC42MTQ0MTIsMTU5Ljc5ODQgMTIwLjE4NzgyMiwxNTguOTI4IEw5Ni43MDI5MzU3LDExMC41Njk2IFogTTIwNy45ODUxMTcsMjExLjIgTDE2OC41MDc5MjgsMjExLjIgTDEwNS4xNzM3ODksNzguNjI0IEMxMDQuNjQ0NTYxLDc3LjUxMDQgMTAzLjUxNTU0MSw3Ni44IDEwMi4yNzc0NjksNzYuOCBMNzYuNDQ3OTQzLDc2LjggTDc2LjQ3NjgwOTksNDQuOCBMMTI3LjEwMzA2Niw0NC44IEwxOTAuMTQ1MzI4LDE3Ny4zNzI4IEMxOTAuNjc0NTU2LDE3OC40ODY0IDE5MS44MDM1NzUsMTc5LjIgMTkzLjA0MTY0NywxNzkuMiBMMjA3Ljk4NTExNywxNzkuMiBMMjA3Ljk4NTExNywyMTEuMiBaIE0yMTEuMTkyNTU4LDE3Mi44IEwxOTUuMDcxOTU4LDE3Mi44IEwxMzIuMDI5Njk2LDQwLjIyNzIgQzEzMS41MDA0NjgsMzkuMTEzNiAxMzAuMzcxNDQ5LDM4LjQgMTI5LjEzMDE2OSwzOC40IEw3My4yNzI1NzYsMzguNCBDNzEuNTA1Mjc1OCwzOC40IDcwLjA2ODM0MjEsMzkuODMwNCA3MC4wNjUxMzQ0LDQxLjU5NjggTDcwLjAyOTg1MjgsNzkuOTk2OCBDNzAuMDI5ODUyOCw4MC44NDggNzAuMzYzNDI2Niw4MS42NjA4IDcwLjk2OTYzMyw4Mi4yNjI0IEM3MS41Njk0MjQ2LDgyLjg2NCA3Mi4zODQxMTQ2LDgzLjIgNzMuMjM3Mjk0MSw4My4yIEwxMDAuMjUzNTczLDgzLjIgTDE2My41OTA5MiwyMTUuNzc2IEMxNjQuMTIzMzU1LDIxNi44ODk2IDE2NS4yNDU5NiwyMTcuNiAxNjYuNDg0MDMyLDIxNy42IEwyMTEuMTkyNTU4LDIxNy42IEMyMTIuOTY2Mjc0LDIxNy42IDIxNC40LDIxNi4xNjY0IDIxNC40LDIxNC40IEwyMTQuNCwxNzYgQzIxNC40LDE3NC4yMzM2IDIxMi45NjYyNzQsMTcyLjggMjExLjE5MjU1OCwxNzIuOCBMMjExLjE5MjU1OCwxNzIuOCBaIiBmaWxsPSIjRkZGRkZGIj48L3BhdGg+CiAgICA8L2c+Cjwvc3ZnPg==",
3+
"headers": {
4+
"Content-Type": "image/svg+xml"
5+
},
6+
"isBase64Encoded": true,
7+
"statusCode": 200
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"headers": {
3+
"Accept-Encoding": "gzip"
4+
},
5+
"resource": "/todos",
6+
"path": "/todos",
7+
"httpMethod": "GET"
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import requests
2+
from requests import Response
3+
4+
from aws_lambda_powertools import Logger, Tracer
5+
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
6+
from aws_lambda_powertools.logging import correlation_paths
7+
from aws_lambda_powertools.utilities.typing import LambdaContext
8+
9+
tracer = Tracer()
10+
logger = Logger()
11+
app = APIGatewayRestResolver()
12+
13+
14+
@app.get("/todos", compress=True)
15+
@tracer.capture_method
16+
def get_todos():
17+
todos: Response = requests.get("https://jsonplaceholder.typicode.com/todos")
18+
todos.raise_for_status()
19+
20+
# for brevity, we'll limit to the first 10 only
21+
return {"todos": todos.json()[:10]}
22+
23+
24+
# You can continue to use other utilities just as before
25+
@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST)
26+
@tracer.capture_lambda_handler
27+
def lambda_handler(event: dict, context: LambdaContext) -> dict:
28+
return app.resolve(event, context)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"statusCode": 200,
3+
"headers": {
4+
"Content-Type": "application/json",
5+
"Content-Encoding": "gzip"
6+
},
7+
"body": "H4sIAAAAAAACE42STU4DMQyFrxJl3QXln96AMyAW7sSDLCVxiJ0Kqerd8TCCUOgii1EmP/783pOPXjmw+N3L0TfB+hz8brvxtC5KGtHvfMCIkzZx0HT5MPmNnziViIr2dIYoeNr8Q1x3xHsjcVadIbkZJoq2RXU8zzQROLseQ9505NzeCNQdMJNBE+UmY4zbzjAJhWtlZ57sB84BWtul+rteH2HPlVgWARwjqXkxpklK5gmEHAQqJBMtFsGVygcKmNVRjG0wxvuzGF2L0dpVUOKMC3bfJNjJgWMrCuZk7cUp02AiD72D6WKHHwUDKbiJs6AZ0VZXKOUx4uNvzdxT+E4mLcMA+6G8nzrLQkaxkNEVrFKW2VGbJCoCY7q2V3+tiv5kGThyxfTecDWbgGz/NfYXhL6ePgF9PnFdPgMAAA==",
8+
"isBase64Encoded": true
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"resource": "/subscriptions/{subscription}",
3+
"path": "/payment/subscriptions/123",
4+
"httpMethod": "GET"
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from aws_lambda_powertools import Logger, Tracer
2+
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
3+
from aws_lambda_powertools.logging import correlation_paths
4+
from aws_lambda_powertools.utilities.typing import LambdaContext
5+
6+
tracer = Tracer()
7+
logger = Logger()
8+
app = APIGatewayRestResolver(strip_prefixes=["/payment"])
9+
10+
11+
@app.get("/subscriptions/<subscription>")
12+
@tracer.capture_method
13+
def get_subscription(subscription):
14+
return {"subscription_id": subscription}
15+
16+
17+
@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST)
18+
@tracer.capture_lambda_handler
19+
def lambda_handler(event: dict, context: LambdaContext) -> dict:
20+
return app.resolve(event, context)

0 commit comments

Comments
 (0)